即使未更改,也要停止ActiveRecord保存序列化列

这与散列的Rails部分更新问题非常相似,但问题并没有真正得到回答恕我直言。

问题是这样的:我有一个带序列化列的模型:

class Import < AR::Base serialize :data 

就我而言,在第一次保存/创建模型后,这些数据将会,而且应该不会更改。 所以我想禁用AR的function,它始终保存序列化列(这通常是一个好主意,因为它无法检测到这些更改)。 我想禁用保存,因为数据可能非常大,模型会经常更新。

我已经尝试过monkeypatching到ActiceRecord :: AttributeMethods :: Dirty,如下所示:

 class Import def update(*) if partial_updates? super(changed | (attributes.keys & (self.class.serialized_attributes.keys - ["data"]))) else super end end 

但这似乎没有效果。 有人有更好的主意吗?

这是在Rails 3.0.12下

我最终做了什么,即使它不是对原始问题的真正答案,如下:

 class Import < AR::Base belongs_to :storage class Storage < AR::Base serialize :data 

...即将数据列移动到自己的模型中,并将其与原始模型相关联。 实际上这在概念上有点清洁。

这是一个丑陋的猴子补丁解决方案:

 module ActiveRecord module AttributeMethods module Dirty def update(*) if partial_updates? # Serialized attributes should always be written in case they've been # changed in place. Unless it is 'spam', which is expensive to calculate. super(changed | (attributes.keys & self.class.serialized_attributes.keys - ['spam'])) else super end end private :update end end end class Foo < ActiveRecord::Base serialize :bar serialize :spam def calculate_spam # really expensive code end def cache_spam! calculated_spam = calculate_spam @changed_attributes['spam'] = [spam, calculated_spam] self.update_attribute(:spam, calculated_spam) end end 

您必须记住调用cache_spam!,否则您的序列化属性将永远不会被保存。