LoginSignup
2
5

More than 5 years have passed since last update.

kakurenbo_putiを使いつつaccepts_nested_attributes_for :hoges, allow_destroy: trueしたい場合

Posted at

論理削除でもallow_destroy: trueしたい

データの持ちかたの関係上、論理削除が必要になったので、gem kakurenbo_putiを使って実装したのですが、そのモデルがfields_forを使って保存・削除するタイプのモデルだったもんで、どうしたものかと小一時間悩みました。

Hogeモデル
class Hoge < ActiveRecord::Base
  belongs_to :foo
  soft_deletable column: :deleted_at
end
Fooモデル(before)
class Foo < ActiveRecord::Base
  has_many :hoges, dependent: :destroy, inverse_of: :foo

  # allow_destroy: true だと物理削除されてしまう件
  accepts_nested_attributes_for :hoges, allow_destroy: true
end

accepts_nested_attributes_forの更新処理をカスタマイズ

調べていたら、accepts_nested_attributes_forの更新処理をカスタマイズするという投稿を見つけました。
これを使えばできそうです。

Fooモデルを改修する

Fooモデル(after)
class Foo < ActiveRecord::Base
  has_many :hoges, dependent: :destroy, inverse_of: :foo

  # allow_destroy: trueを残すと事故で消されかねないので消しておく
  accepts_nested_attributes_for :hoges

  # accepts_nested_attributes_forの更新処理をカスタマイズ
  # @see http://qiita.com/tkyowa/items/e751dcf8958b8c86b686
  def hoges_attributes=(listed_attributes)
    listed_attributes.each do |index, attributes|
      hoge = hoges.detect { |hoge|
        hoge.id == attributes['id'].to_i
      } || hoges.build
      _destroy = attributes.delete("_destroy")
      if _destroy
        attributes["deleted_at"] = Time.zone.now
      end
      hoge.assign_attributes(attributes)
    end
  end
end

解説します。
allow_destroy: trueを設定している場合、_destroyという属性が一緒に渡ってきていてそれを反映させると、物理的に削除されるので、attributes.delete("_destroy")でその属性を削除しています(値は_destroyという変数にとっておく)。

属性がない場合にdeleteメソッドが実行された場合は_destroyの値はnilなので何もしませんが、ある場合はkakurenbo_putiの論理削除用に作ったカラム(ここではdeleted_atカラム)に現在時刻を設定してアサインしておきました。

これで、ネストされたモデルであっても論理削除が可能となりました。

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5