在Ruby on Rails中重写setter方法的正确方法是什么?

我正在使用Ruby on Rails 3.2.2,我想知道是否以下是一个“正确”/“正确”/“确定”的方式来覆盖我的类属性的setter方法。

attr_accessible :attribute_name def attribute_name=(value) ... # Some custom operation. self[:attribute_name] = value end 

上面的代码似乎按预期工作。 但是, 我想知道,通过使用上面的代码,将来我是否会遇到问题,或者至less是Ruby on Rails会“出现什么问题” 。 如果这不是重写setter方法的正确方法,那么正确的方法是什么?


注意 :如果我使用的代码

 attr_accessible :attribute_name def attribute_name=(value) ... # Some custom operation. self.attribute_name = value end 

我得到以下错误:

 SystemStackError (stack level too deep): actionpack (3.2.2) lib/action_dispatch/middleware/reloader.rb:70 

================================================== ========================= 更新:2017年7月19日

现在Rails文档也build议像这样使用super

 class Model < ActiveRecord::Base def attribute_name=(value) # custom actions ### super(value) end end 

================================================== =========================

原始答复

如果要在通过模型访问时覆盖表的列的setter方法,则可以这样做。

 class Model < ActiveRecord::Base attr_accessible :attribute_name def attribute_name=(value) # custom actions ### write_attribute(:attribute_name, value) # this is same as self[:attribute_name] = value end end 

请参阅覆盖 Rails文档中的默认访问器 。

因此,您的第一个方法是在Ruby on Rails的模型中重写列设置器的正确方法。 这些访问器已经由Rails提供,作为模型的属性访问表的列。 这就是我们所说的ActiveRecord ORM映射。

另外请记住, 模型顶部attr_accessible与访问器无关。 它有一个完全不同的function(见这个问题 )

但是在纯Ruby中,如果你已经定义了一个类的访问器并且想要重写setter,那么你必须使用如下的实例variables:

 class Person attr_accessor :name end class NewPerson < Person def name=(value) # do something @name = value end end 

一旦你知道了attr_accessor作用,这将更容易理解。 代码attr_accessor :name相当于这两个方法(getter和setter)

 def name # getter @name end def name=(value) # setter @name = value end 

此外,你的第二个方法失败,因为它会导致无限循环,因为你正在调用相同的方法attribute_name=在该方法。

使用super关键字:

 def attribute_name=(value) super(value.some_custom_encode) end 

相反,为了覆盖读者:

 def attribute_name super.some_custom_decode end 

在铁轨4

假设你在表中有年龄属性

 def age=(dob) now = Time.now.utc.to_date age = now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1) super(age) #must add this otherwise you need to add this thing and place the value which you want to save. end 

注意:对于rails 4中的新angular色 ,您不需要在模型中指定attr_accessible 。 相反,您必须使用允许方法在控制器级别上列出您的属性。

我发现(至less对于ActiveRecord关系集合)下面的模式工作:

 has_many :specialties def specialty_ids=(values) super values.uniq.first(3) end 

(这将抓取数组中前3个非重复条目。)

使用attr_writer覆盖setter attr_writer:attribute_name

  def attribute_name=(value) # manipulate value # then send result to the default setter super(result) end 
Interesting Posts