2011-02-10 6 views
3

나는 width, heightdepth 속성을 기반으로 설정하려는 dimensions이라는 속성이 있습니다.가상 속성을 기준으로 activerecord 속성을 설정합니다.

예를 들면, 난 ShippingProfile.find(1).width = 4 싶지, 그것은 같은 크기로 저장 한 {폭 => 4 : 세로 => 0 : 깊이 => 0}`

이 가능한가?

class ShippingProfile < ActiveRecord::Base 
    after_initialize :set_default_dimensions 

    serialize :dimensions, Hash 

    attr_accessor :width, :height, :depth 
    attr_accessible :width, :height, :depth, :dimensions 

    private 

    def set_default_dimensions 
     self.dimensions ||= {:width => 0, :height => 0, :depth => 0} 
    end 
end 
+0

ShippingProfile.find (1) .dimensions.width = 4가 더 좋을 것이라고 생각하지 않습니까? – macarthy

답변

7

매우 그렇다, 당신이 할 필요가 self.dimensions의 값을 설정하는 콜백을 사용하는 것입니다 : 당신은 당신이 어떤을 유지하도록 self.foo || self.dimensions[:foo]를 사용할 필요가

class ShippingProfile < ActiveRecord::Base 
    after_initialize :set_default_dimensions 
    after_validation :set_dimensions 

    serialize :dimensions, Hash 

    attr_accessor :width, :height, :depth 
    attr_accessible :width, :height, :depth, :dimensions 

    private 

    def set_default_dimensions 
    self.dimensions ||= {:width => 0, :height => 0, :depth => 0} 
    end 

    def set_dimensions 
    self.dimensions = { 
     :width => self.width || self.dimensions[:width], 
     :height => self.height || self.dimensions[:height], 
     :depth => self.depth || self.dimensions[:depth], 
    } 
    end 
end 

을 이미 해시에 설정된 기존 값 왜? 귀하의 차원 특성 (전 가정) 데이터베이스에서 유지되지 않습니다 - 당신 attr_accessor, 테이블에 필드로 그들을 설정하는 대신 사용하고 있습니다.

제쳐두고, 나는 모델 디자인에 대해 잘못된 생각을하고 있다고 생각합니다. 데이터베이스에 해시로 차원을 저장하면 이러한 특성을 기반으로 쿼리 할 수있을뿐만 아니라 불필요한 취약성을 추가 할 수 있습니다.

이 개별 특성을 개별 필드로 저장하는 인 경우 중복성과 복잡성을 도입하게됩니다.

class ShippingProfile < ActiveRecord::Base 
    def dimensions 
    { :width => self.width, :height => self.height, :depth => self.depth } 
    end 
end 

이런 식으로, 당신은 기능을 유지 : 당신은 더 나은이 필요한 경우 다음 즉석에서 치수 해시를 생성, (당신이 이미하지 않은 경우) 데이터베이스의 필드로 세 가지 특성을함으로써 제공 될 것입니다 유연성을 확보 할 수 있습니다.

당신은 직렬화의 클래스를 사용할 수 있습니다
+0

그래서 개인 차원을 저장하는 데갔습니다. 당신이 말했듯이 문제가 훨씬 적 었으며 질의를 통해 훨씬 더 유연했습니다. 때로는 멋진 DB를 유지하는 데 익숙해 져 있지만 실제로는 그럴 필요가 없습니다. :) – brewster

0
ShippingProfile.find(1).dimensions[:width] = 4 
0

, 그래서 지금

class ShippingProfile < ActiveRecord::Base 
    serialize :dimensions, Dimensions 
end 

class Dimensions 
    attr_accessor :width, :height,:depth 

    def initialize 
    @width = 0 
    @height = 0 
    @depth = 0 
    end 

    def volume 
    width * height * depth 
    end 
end 

당신이 ShippingProfile.dimensions.width = 1 이후 ShippingProfile.dimension.volume 등을 수행 할 수 있습니다 ..

모델이 될 것 해시보다 더 풍부한 표현

관련 문제