Ruby on RailsのCRUDを学ぶ。Delete編。deleteメソッドとdestroyメソッド

 

Ruby On RailsでCRUDを学ぶ。

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
関連記事

  << Ruby On Railsまとめに戻る