Ruby on RailsのCRUDを学ぶ。Delete編。deleteメソッドとdestroyメソッド
RailsのCrud第4回目今回はdelete編です。
deleteメソッドとdestroyメソッド
Railsでレコードを削除する場合はdeleteとdestroyメソッドを使います。
deleteとdestroyメソッドの違いは、deleteがactive recordを介さずに直接SQLを発行するのに対してdestroyはactive recordを介すというところです。
destroyの場合はあらかじめモデルにリレーションを設定してdependent: destroyをセットしておくと関連したモデルもまとめて削除してくれます。 一方、deleteの方は直接SQLを発行するので、他のリレーションなどと関係なくレコードを削除します。
class Category < ActiveRecord::Base
has_many :posts, dependent: destroy
end
class Post < ActiveRecord::Base
belong_to :category
end
この例では、categoryとpostが一対多の関係で定義されて、dependent: destroyが定義されているため、 ブログのあるカテゴリを削除するとそのカテゴリに属するブログも一緒に削除されます。
deleteをしようすると使わなくなった古いデータが残ってしまうこともあるので、 特段deleteを使う理由がなければ、destroyを利用するのが望ましいです。
destroyとdestroy!
active recordの!つきメソッドはレコードの作成・更新・削除に失敗した時にfalseを返すわけではなく、例外を発生させます。
destroyとdestroy!メソッドも例外なくこれと同じ前ような挙動になります。
トランザクション内で、ロールバックさせたい時は例外が発生しないとロールバックされないのでdestroy!が望ましくそれ以外はdestroyという感じで使い分けましょう。
# レコードの削除に失敗してもロールバックされない
ActiveRecord::Base.transaction do
hoge.destroy
end
# レコードの削除に失敗すると例外が発生しロールバックされる
ActiveRecord::Base.transaction do
hoge.destroy!
end
なお、destroyとdestroy!メソッドはバリデーションを行わないため、それぞれのメソッドでレコードの削除可否をチェックする処理はbefore_destroyなどのコールバックメソッドに定義します。
before_destroy do |record|
errors.add :base, 'バリデーションエラー'
throw :abort
end
複数レコードの削除。destroy_allとdelete_all
複数のレコードを削除する場合は以下のようなコードになります。
Blog.where('published_at <= ?', '2017-07-30').destroy_all
コードでは2017年7月30日より古い記事を削除しています。
複数レコードの削除では、destroyall,deleteallで可能ですが、先に書いたようにdelete系のメソッドでは、 直接SQLが実行されるので特段理由がなければdestroy_allを使うようにしましょう。
まとめ
まとめです。
- レコードの削除はdelete,destroyメソッド
- 特段理由がなければdestroyメソッドを使う
- !つきメソッドとなしメソッドの違いは例外を発生させるかどうか
- 削除のバリデーションはbefore_destoryで行う
- 複数レコードの削除はdestroy_all or delete_all