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


98

我正在尝试覆盖ActiveRecord模型的getter方法。我name在模型中有一个称为的属性Category,我希望能够执行以下操作:

def name
  name_trans || name
end

如果name_transattribute不为nil,则返回它,否则返回nameattribute。我该怎么做?

然后通常应这样调用:

@category.name

Answers:



98

更新:根据《Rails样式指南》的首选方法是使用self[:name]代替read_attributewrite_attribute。我鼓励您跳过我的答案,而选择这个答案。


您可以完全那样做,除了需要使用它read_attribute来实际获取name属性的值并避免对name方法的递归调用:

def name 
  name_trans || read_attribute(:name)
end

2
任何想法,为什么Rubocop喜欢self[:name]read_attribute[:name]
Zack Xu

18

我想添加另一个覆盖getter方法的选项,它就是:super。

def name
  name_trans || super
end

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


1
这是Rails指南当前针对吸气剂和塞脂
2018年

5

覆盖getter和using read_attribute不适用于关联,但是可以alias_method_chain代替使用。

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override

你能举一个合适的例子吗?
奥雅纳(Arup Rakshit)2015年

好。我刚刚看到了doco。现在,如果我调用name模型对象,则将哪个对象称为- name_with_overridename_without_override
奥雅纳(Arup Rakshit)2015年

1
name现在将致电name_with_override。如果由于某种原因要调用原始方法,可以调用name_without_override
Patrick Oscity

OI看..谢谢您的答复//
Arup Rakshit

2

如果您使用这样的商店属性

store :settings, accessors: [:volume_adjustment] 

或使用宝石链接hstore_accessor 宝石

因此,您最终store在模型上使用了方法,然后要覆盖那些您不能使用的方法self.read_attribute,您必须改为使用super

def partner_percentage
  super.to_i || 10
end

0

如果有人要name_trans在getter方法之后更新值,则可以使用self [:name] =。

def name
  self[:name] = name_trans || self[:name]
  # don't do this, it will cause endless loop
  # update(name: name_trans)
end

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.