虚拟属性中的self,self [:item]与委托的区别

时间:2012-01-24 01:16:08

标签: ruby-on-rails ruby ruby-on-rails-3

有些东西让我感到困惑,我想请一些澄清,因为它给我带来了一些麻烦。

我有一个城市模型,其中包含一个wood_production属性的委托,该属性指定该城市的木材数量。就像:

has_one :wood_production, :autosave => true
delegate :amount, :to => :wood_production, :prefix => true, :allow_nil => true

    def wood
        wood_production_amount
    end

    def wood= amt
      self[:wood_production_amount] = amt
    end

我通常希望能够做一个city.wood - = 1000并且通过这个城市保存这个价值,但是我遇到了各种各样的问题。似乎我没有正确设置我的虚拟属性。

所以我真的想问一下,这些之间的区别是什么:

def wood
    self.wood_production_amount
end

def wood
    wood_production_amount
end

def wood
    self[:wood_production_amount]
end

应该用什么才能正确处理这种情况?

编辑:

如果我创建了这样的setter:

def wood= amt
  self.wood_production_amount = amt
end

我明白了:

1.9.2p290 :003 > c.wood -= 1000
 => 58195.895014789254 
1.9.2p290 :004 > c.save
   (0.1ms)  BEGIN
   (0.3ms)  UPDATE `wood_productions` SET `amount` = 58195.895014789254, `updated_at` = '2012-01-24 02:13:00' WHERE `wood_productions`.`id` = 1
   (2.0ms)  COMMIT
 => true

1.9.2p290 :005 > c.wood
 => 66522.63434300483         ???????

如果设置者是:

def wood= amt
  wood_production_amount = amt
end

1.9.2p290 :004 > c.wood -= 1000
 => 58194.823000923556 
1.9.2p290 :005 > c.save
   (0.1ms)  BEGIN
   (0.2ms)  COMMIT
 => true

1 个答案:

答案 0 :(得分:2)

回答第一部分self.wood_production_amountwood_production_amount功能相同。唯一的区别是,在后者中,自我是隐含的,是城市模型的当前实例。我很少使用self.anything,除非它是必需的。

在大多数情况下,

self[:wood_production_amount]在功能上与前两个类似。不同之处在于它允许您轻松覆盖默认的访问器方法。 read_attribute(:attribute)在功能上与self[:attribute]相同。例如,假设您的City模型具有state属性,但您希望在请求时始终以大写形式返回状态。你可以这样做:

class City < ActiveRecord::Base
  def state
    self[:state].try(:upcase)
    # or
    read_attribute(:state).try(:upcase)
  end
end

city = City.new(:state => 'vermont')
city.state # => VERMONT

所以要回答你的第二个问题,这实际上取决于你想如何使用它。就个人而言,我会使用委托方法,除非您需要覆盖某些行为。它不适合你的原因可能是你没有委托setter方法:amount=

delegate :amount, :amount= :to => :wood_production, 
         :prefix => true, :allow_nil => true