我正在使用 Ruby on Rails 3.2.2,我想知道以下是否是覆盖我的类属性的 setter 方法的“正确”/“正确”/“确定”方式。
attr_accessible :attribute_name def attribute_name=(value) ... # Some custom operation. self[:attribute_name] = value end
上面的代码似乎按预期工作。但是, 我想知道,通过使用上面的代码,将来我是否会遇到问题,或者至少,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 文档也建议这样使用super:
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 模型顶部的 与访问器无关。它具有完全不同的功能(请参阅此问题)
attr_accessible
但是在纯 Ruby 中,如果你为一个类定义了访问器并且想要覆盖 setter,你必须像这样使用实例变量:
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)
attr_accessor
attr_accessor :name
def name # getter @name end def name=(value) # setter @name = value end
您的第二种方法也失败了,因为当您在该方法中调用相同的方法时,它会导致无限循环attribute_name=。
attribute_name=