如何将has_one / has_many关联标记为脏?

时间:2012-09-25 15:56:01

标签: ruby-on-rails ruby-on-rails-3 activerecord

我一直在寻找AR中的这种功能,但似乎无法找到它。 AR的Dirty实现表明,如果其中一个直接属性发生了变化,那么已经存在的实例将被视为脏。所以,让我们说:

class Picture < ActiveRecord::Base
  belongs_to :gallery
  has_one :frame
end

在这种情况下,我可以做类似的事情:

p = Picture.new(:gallery => Gallery.new, :frame => Frame.new)
p.save #=> it will save the three instances
p.gallery = Gallery.new
p.save #=> will not save the new gallery
p.gallery_id_will_change!
p.gallery = Gallery.new
p.save #=> this will save the new Gallery

但是现在我不能为has_one关联做类似的事情,因为Picture实现没有引用它的属性。所以,似乎这样的脏标记是不可能的。或者不是吗?

2 个答案:

答案 0 :(得分:1)

我能想到的最好的事情是:

class Picture < ActiveRecord::Base
  belongs_to :gallery
  has_one :frame

  after_save :force_save_frame

  def force_save_frame
    frame.save! if frame.changed?
  end
end

答案 1 :(得分:1)

weexpectedTHIS类似,表示为模型本身的属性设置脏标志,而不是为相关对象设置。它仅适用于belongs_to,因为模型上有一个外键。

但是你可以像这样做伎俩

module FrameDirtyStateTracking
  def frame=(frame)
    attribute_will_change!('frame')
    super
  end
end

class Picture < ActiveRecord::Base
  prepend FrameDirtyStateTracking

  belongs_to :gallery
  has_one :frame
end

picture = Picture.new
picture.frame = Frame.new
picture.changed? # => true
picture.changed # => ['frame']