1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

nested_attributesの中のattr_accessorが時々callbackを発火させない件

Posted at

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_attributesattr_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

参考

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?