记录attribute =和Array.push的更改

时间:2016-08-31 20:39:20

标签: ruby-on-rails postgresql

对于与postgres数组相关的属性,ActiveModel :: Dirty没有覆盖Array.push(或者我最近读过的任何其他的就地修改方法){{ 3}}完善的。例如,如果Apple模型具有Apple.seeds数组,您将在Rails控制台中看到以下内容。

johnny = Apple.new()
# => <Apple #blahblahblah>
johnny.seeds
# => [] (assuming [] default)
johnny.seeds << "Oblong"
# => ["Oblong"]
johnny.changed?
# => false
johnny.seeds = []
johnny.seeds += ["Oblong"]
# => ["Oblong"]
johnny.changed?
# => true

因此,您可以使用两种不同的方式更改数组属性,但Rails只识别使用setter的方法。我的问题是,是否有一种方法(不会破坏Array类)使得push在ActiveRecord对象的上下文中表现得像一个setter,因此johnny.seeds << (x)将反映在{{1}中}?

(在我看来,这是为了防止未来的开发人员使用推送数组属性,无意中无法记录更改,因为他们没有意识到这种限制。)

1 个答案:

答案 0 :(得分:1)

任何具有可变对象的列都存在问题,而不仅仅是Array对象。

seeder = Apple.first
seeder.name
=> "Johnny "

seeder.name << " Appleseed"
seeder.changed?
=> false

您最好为未来的开发人员留言,但除此之外您可以考虑更换changed?方法

class Apple

  alias_method 'old_changed?', 'changed?'

  def changed?
    return old_changed? if old_changed?
    return (seeds.count > 0) if new_record?
    return seeds != Apple.find(id).seeds
  end

end

但是,请注意,仅仅因为changed?返回true,并不能保证在update_attributes中更新未更改object_id的字段...您可能会发现它们是不。您可能需要聘请了解这些陷阱的合格铁路开发人员。