2012-04-02 49 views
6

這與Rails partial updates problem with hashes非常相似,但問題還沒有真正回答過恕我直言。停止ActiveRecord即使沒有改變,也會保存一個序列化列

問題是這樣的:我有一個序列化的柱的模型:

class Import < AR::Base 
    serialize :data 

在我而言,這個數據會,也應該不會改變後的第一個保存/模型的創建。所以我想禁用AR總是保存序列化列的功能(這通常是一個好主意,因爲它無法檢測到這些更改)。我想禁用保存,因爲數據可能非常大,並且模型會經常更新。

我已經嘗試過的Monkeypatching到ActiceRecord :: AttributeMethods ::髒這樣的:

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

回答

6

我最終什麼事做,即使它不是一個真正的答案,原來的問題,如下:

class Import < AR::Base 
    belongs_to :storage 

class Storage < AR::Base 
    serialize :data 

...即。將數據列移動到它自己的模型中,並將其與原始模型相關聯。這實際上在概念上更清潔。

+0

這實際上很有意義,謝謝分享見解。我想我會沿着同樣的道路走下去,並且在_Storage_模型和其他擁有隻讀序列化列的模型之間使用多態關聯 – 2012-06-01 12:10:28

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!或您的序列化的屬性將永遠不會被保存。

相關問題