如何在ActiveRecord模型中覆盖getter方法?

115

我正在尝试重写一个ActiveRecord模型的getter方法。在模型Category中有一个称为name的属性,我希望能够做到这样:

def name
  name_trans || name
end

如果name_trans属性不为nil,则返回它,否则返回name属性。我应该怎么做?

然后可以像这样正常调用:

@category.name
7个回答

167

Rails风格指南建议使用self[:attr]而非read_attribute(:attr)

你可以像这样使用它:

def name
  name_trans || self[:name]
end

为什么这样做更好?不要只是链接到其他网站,包括相关的部分在这里。链接可能会失效。 - JamesT
2
更多上下文请参见此处:https://github.com/bbatsov/rails-style-guide/issues/155 - mimsugara

101
更新:根据Rails样式指南的首选方法是使用self[:name]而不是read_attributewrite_attribute。我鼓励您跳过我的答案,转而选择这个答案
你可以像那样做,只需使用read_attribute来实际获取名称属性的值并避免递归调用name方法:
def name 
  name_trans || read_attribute(:name)
end

3
有什么想法可以说明为什么 Rubocop 更喜欢使用 self[:name] 而不是 read_attribute[:name] - Zack Xu

28

我希望为重写 getter 方法增加另一种选项,这个选项就是简单地使用:super。

def name
  name_trans || super
end

这不仅适用于属性的getter方法,而且也适用于关联的getter方法。


2
这是Rails指南当前建议的getter和setter方法:http://api.rubyonrails.org/classes/ActiveRecord/Base.html#class-ActiveRecord::Base-label-Overwriting+default+accessors - sandre89

5

覆盖getter方法并使用read_attribute无法处理关联对象,但您可以使用alias_method_chain来解决。

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override

你能给一个恰当的例子吗? - Arup Rakshit
好的。我刚刚看到了文档。现在,如果我在模型对象上调用name,哪一个会被调用——name_with_override还是name_without_override - Arup Rakshit
1
现在将调用 name_with_override 方法。如果您因某种原因想要调用原始方法,可以调用 name_without_override - Patrick Oscity
哦,我明白了。谢谢你的回复// - Arup Rakshit
这个答案在Rails 5中已经被弃用:弃用alias_method_chain,转而使用Module#prepend - user2553863

2
如果您像这样使用存储属性:
store :settings, accessors: [:volume_adjustment] 

或者使用像 hstore_accessor 这样的宝石 宝石链接

所以你最终使用了模型上的 store 方法,然后要覆盖这些方法,你不能使用 self.read_attribute,而必须使用 super,如下所示:

def partner_percentage
  super.to_i || 10
end

2
如果有人想要在getter方法中更新name_trans后的值,可以使用self[:name]=。
def name
  self[:name] = name_trans || self[:name]
  # don't do this, it will cause endless loop
  # update(name: name_trans)
end

0
你可以使用Rails中的read_attribute方法。Rails文档

虽然这个链接可能回答了问题,但仅提供链接的答案在SO上是不允许的,请从链接背后的内容中添加一些上下文到你的答案中。谢谢! :) - AT82

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接