TL;DR
class User < ApplicationRecord
has_many :comments, dependent: :destroy
accepts_nested_attributes_for :comments, allow_destroy: true
end
class Comment < ApplicationRecord
attribute :foo, :string
after_validation do
p "foo: #{foo}"
end
end
User.last.update(comments_attributes: { id: 1, foo: 'Foo' })
=> true
"foo: Foo"
# この時`comment`の`updated_at`も更新されること
発端
とあるプロジェクトがコメントの添付画像の削除機能が必要でしたが、普通にattr_accessor :img_destroy
でフラグ置きました。
ただし実装したところ、「コメント変更して、添付画像の削除はできるが、コメントを変更せず、添付画像の削除ができない」との報告が来ました。
調べたところ、nested_attributes
の attr_accessor
のみ変更を行う際、after_validation
などのcallbackは実行されない現象が発覚しました。
対処法
いろいろ調べた結果、 Rails 5.1+からのattribute
機能を利用すればいいとわかりました。
もしRails 5.1以下の場合、attr_accessor
が変更される際にattribute_will_change!
を発火させればいいです。
class Comment < ApplicationRecord
attr_accessor :foo
def foo_attr=(value)
attribute_will_change!(:foo)
self.foo = value
end
...
end