2011-02-10 74 views
3

我有一個屬性叫做dimensions我想根據我的width,heightdepth屬性來設置。基於虛擬屬性設置主動記錄屬性

例如,我想要做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 2011-02-10 02:06:21

回答

7

正是這樣,所有你需要做的是使用一個回調來設置self.dimensions值:

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 

您需要使用self.foo || self.dimensions[:foo],以確保您保留任何現有值已經在散列中設置。爲什麼?你的維度屬性(我假設)沒有被保存在數據庫中 - 你正在使用attr_accessor,而不是將它們設置爲表中的字段。

順便說一句,我認爲你正在以錯誤的方式去討論你的模型設計。通過將維度存儲爲數據庫中的散列值,不僅會失去基於這些屬性進行查詢的能力,還會增加不需要的脆弱級別。

如果您的將您的個別維度屬性存儲爲單獨的字段,那麼您將引入冗餘和複雜性。

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

這樣,你保留功能:你會被具有三個屬性的字段在數據庫中(如果你沒有的話),然後在飛行中產生的尺寸哈希時,它需要得到更好的服務並獲得一些靈活性。

+0

所以我去存儲各個維度。它的問題就不那麼嚴重了,就像你說的那樣,查詢更加靈活。有時我會陷入一個漂亮的數據庫中,但實際情況是,我從來沒有真正看過它:) – brewster 2011-04-05 08:25:49

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等。

的模型將是一個比哈希更豐富的表示