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

时间:2012-04-02 17:53:16

标签: ruby-on-rails activerecord serialization partial updates

这与Rails partial updates problem with hashes非常相似,但问题并没有真正得到解答恕我直言。

问题在于:我有一个带有序列化列的模型:

class Import < AR::Base
  serialize :data

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

我已经尝试过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

2 个答案:

答案 0 :(得分:6)

我最终做了什么,即使它不是原来问题的答案,但是如下:

class Import < AR::Base
  belongs_to :storage

class Storage < AR::Base
  serialize :data

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

答案 1 :(得分:3)

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

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 !,否则您的序列化属性将永远不会被保存。