2011-02-10 68 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等。

的模型将是一个比哈希更丰富的表示