今回は、ActiveRecordオブジェクトが保存済みかどうか確認するメソッド persisted? を紹介します。
結論
インスタンスが保存済みかどうかをチェックするメソッド
# インスタンスを新規作成・未保存
pry(main)> pokemon = Pokemon.new(name: 'ミミッキュ')
pry(main)> pokemon.persisted?
=> false
pry(main)> pokemon.new_record?
=> true
# インスタンスをDBに保存
pry(main)> pokemon.save!
pry(main)> pokemon.persisted?
=> true
pry(main)> pokemon.new_record?
=> false
# インスタンスをDBから削除
pry(main)> pokemon.destroy!
pry(main)> pokemon.persisted?
=> false
pry(main)> pokemon.new_record?
=> false
目次
環境
OS: MacOS
メモリ: 32GB
Dependents
Rails6
Ruby 2.6
CentOS7 on Vagrant
Mysql 5.7
persisted?メソッドとは
レコードが保存されているかどうかでUIの表示を切り替えたり、
保存されている場合だけ処理を行いたい場合があります。
そんな時は、persisted?を使用すると便利です。
公式ドキュメントはこちらです。
persisted? | Railsドキュメント
簡単に使い方を紹介します!
保存済みであれば、ボタンを表示する
persisted? をviewで使用するケースを考えてみます。
例えば、新規作成画面と編集画面が多くのアプリには存在すると思います。
下のコードは、アイテムが存在する時だけ、削除ボタンを表示させるviewのサンプルコードです。
# form.html.erb
<%= form_with(model: pokemon, local: true, url: path) do |form| %>
<div>
<%= form.label :name %>
<%= form.text_field :name, placeholder: 'ミミッキュ' %>
</div>
<div>
<%= form.label :level %>
<%= form.text_field :level, placeholder: '50' %>
</div>
<div>
<%= form.submit '登録' %>
# レコードが存在する場合は、削除ボタンを表示する
<% if pokemon.persisted? %>
<%= link_to '削除', pokemon_path(pokemon), method: :delete, data: {confirm: '削除しますか?'} %>
<% end %>
</div>
<% end %>
編集するときに「登録」というボタン名もちょっと変なので
更新、という名前に変えたりする場合は以下のように、切り分けることもできます。
<div>
<% if pokemon.persisted? %>
<%= form.submit '更新' %>
<%= link_to '削除', pokemon_path(pokemon), method: :delete, data: {confirm: '削除しますか?'} %>
<% else %>
<%= form.submit '登録' %>
<% end %>
</div>
似たようなメソッド
persisted?と似たメソッドで、new_record?というメソッドがあります。
こちらは、新しいレコードだった場合にtrueを返すメソッドです。
new_record? | Railsドキュメント
new_record?
さっきの例を、new_record?を使って書いてみると、こうなります。
new_recordがtrueということは、新規作成時なので、登録ボタンを表示させています。
<div>
# 新しいレコードだったら、登録ボタンを表示する
<% if pokemon.new_record? %>
<%= form.submit '登録' %>
<% else %>
<%= form.submit '更新' %>
<%= link_to '削除', pokemon_path(pokemon), method: :delete, data: {confirm: '削除しますか?'} %>
<% end %>
</div>
persisted?とnew_record?の挙動の違いを、タイミングごとにまとめました。
# インスタンスを新規作成・未保存
pry(main)> pokemon = Pokemon.new(name: 'ミミッキュ')
pry(main)> pokemon.persisted?
=> false
pry(main)> pokemon.new_record?
=> true
# インスタンスをDBに保存
pry(main)> pokemon.save!
pry(main)> pokemon.persisted?
=> true
pry(main)> pokemon.new_record?
=> false
# インスタンスをDBから削除
pry(main)> pokemon.destroy!
pry(main)> pokemon.persisted?
=> false
pry(main)> pokemon.new_record?
=> false
まとめ
今回は、persisted?とnew_record?というメソッドについて紹介しました。
persisted?は、レコードが保存されていたらtrue、
new_record?は、レコードが保存されていなかったらtrue、をそれぞれ返します。
インスタンスが削除されていた場合は、どちらもfalseを返すという点もポイントです。