2012-04-02 2 views
6

이것은 Rails partial updates problem with hashes과 매우 유사하지만 질문에 대해서는 실제로 IMHO로 대답하지 않았습니다. ActiveRecord가 변경되지 않은 경우에도 직렬화 된 열 저장

문제

은 이것이다 : 나는 직렬화 된 열이있는 모델이 : 내 경우

class Import < AR::Base 
    serialize :data 

를 첫 번째/모델의 생성을 저장 한 후이 데이터 및 변경해서는 안됩니다. 따라서 항상 직렬화 된 열을 저장하는 AR의 기능을 비활성화하려고합니다 (일반적으로 좋은 생각인데, 변경 사항을 감지 할 수 없기 때문입니다). 데이터가 상당히 클 수 있고 모델이 자주 업데이트되므로 저장을 비활성화하고 싶습니다.

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

을하지만,이 효과가 없습니다 것 같다 :

는 이미 ActiceRecord :: AttributeMethods :: 같은 더러운로 monkeypatching 시도했습니다. 누구 더 좋은 생각있어?

이, 원래의 질문에 대한 답변이 정말로, 비록 레일 내가하고 결국 무엇 3.0.12

답변

6

아래에있는 다음과 같다 :

class Import < AR::Base 
    belongs_to :storage 

class Storage < AR::Base 
    serialize :data 

... 즉. 데이터 열을 자체 모델로 이동하고 원래 모델과 연관시킵니다. 실제로 개념적으로 다소 깨끗합니다. 당신은 cache_spam!, 또는 직렬화 속성이 저장되지 않습니다 전화를 기억해야합니다

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 

:

+0

실제로 통찰력을 공유해 주셔서 감사합니다. 나는 같은 경로로 가서 _Storage_ 모델과 읽기 전용 직렬화 된 컬럼을 가진 다른 것들 사이의 다형성 연관을 사용할 것이라고 생각한다. –

3

여기 못생긴 원숭이 패치 솔루션입니다.

관련 문제