2009-12-23 2 views
1

레일스의 id 값에 따라 파생 된 속성을 어떻게 유지합니까? 아래 스 니펫이 작동하는 것 같습니다. 더 나은 레일 방법이 있습니까?id 값에 따라 달라지는 ActiveRecord 속성 지속성

class Model < ActiveRecord::Base 
    .... 
    def save 
    super 
    #derived_attr column exists in DB 
    self.derived_attr = compute_attr(self.id) 
    super 
    end 
end 

답변

5

콜백 기능이 있으므로 save를 오버라이드 할 필요가 없습니다. 다음 코드의 before_save 호출은 질문의 모든 코드와 기능적으로 동일합니다.

필자는 set_virtual_attr을 공개하여 필요에 따라 계산할 수 있도록했습니다.

class Model < ActiveRecord::Base 
    ... 
    # this one line is functionally equivalent to the code in the OP. 
    before_save :set_virtual_attr 
    attr_reader :virtual_attr 

    def set_virtual_attr 
    self.virtual_attr = compute_attr(self.id) 
    end 
    private 
    def compute_attr 
    ... 
    end 
end 
+0

을 보여줍니다. –

+1

일 수 있지만 일반적으로 속성은 해당 DB 열이 없기 때문에 가상입니다. 일반적으로 기존 열에서 파생됩니다. 레일스의 경우 가상 속성에 대한 다른 정의에 대해 들어 본 적이 없습니다. – EmFi

+0

좋은 지적. 가상 속성 대신 파생 된 속성을 사용하는 질문에 대해 다시 말합니다. –

3

나는 가상 속성에 대한 사용자 정의 세터를 제공하고 레코드를 만든 후 값을 설정하는 after_create 훅을 제공하는 것이 일을 더 허용 방법을 생각한다.

다음 코드는 원하는대로 수행해야합니다. 콘솔이 실행

class Virt < ActiveRecord::Base 

    def after_create() 
    self.virtual_attr = nil # Set it to anything just to invoke the setter 

    save # Saving will not invoke this callback again as the record exists 
      # Do NOT try this in after_save or you will get a Stack Overflow 
    end 

    def virtual_attr=(value) 
    write_attribute(:virtual_attr, "ID: #{self.id} #{value}") 
    end 
end 

나는 그가 ID를 기반으로하는 virtual_attr라는 DB에 열이 있다고 가정 않은 다음

v=Virt.new 
=> #<Virt id: nil, virtual_attr: nil, created_at: nil, updated_at: nil> 

>> v.save 
=> true 
>> v 
=> #<Virt id: 8, virtual_attr: "ID: 8 ", created_at: "2009-12-23 09:25:17", 
      updated_at: "2009-12-23 09:25:17"> 

>> Virt.last 
=> #<Virt id: 8, virtual_attr: "ID: 8 ", created_at: "2009-12-23 09:25:17", 
      updated_at: "2009-12-23 09:25:17"> 
관련 문제