rails覆盖关系的默认getter(belongs_to)

所以我知道如何覆盖使用的ActiveRecord对象的属性的默认getter

def custom_getter return self[:custom_getter] || some_default_value end 

然而,我试图为一个属于联盟的人做同样的事情。 例如。

 class Foo < AR belongs_to :bar def bar return self[:bar] || Bar.last end end class Bar < AR has_one :foo end 

当我说:

 f = Foo.last 

我想有方法f.bar返回最后一个酒吧,而不是零,如果该关联不存在。

但是这不起作用。 原因是self [:bar]总是未定义的。 这实际上是自我[:bar_id]。

我可以做一些天真的事情:

 def bar if self[:bar_id] return Bar.find(self[:bar_id]) else return Bar.last end end 

但是,这总是会调用db调用,即使Bar已经被提取,这当然也不是很理想。

有没有人有一个洞察力,我可能有一个关系,这样的belongs_to属性只加载一次,并有一个默认值,如果没有设置。

alias_method是你的朋友在这里。

 alias_method :original_bar, :bar def bar self.original_bar || Bar.last end 

这种方式的工作原理是,你将默认的“bar”方法别名为“original bar”,然后实现你自己的“bar”版本。 如果对original_bar的调用返回nil,则返回最后一个Bar实例。

兰迪的答案是现货,但有一个更简单的方法来写它,使用alias_method_chain:

 def bar_with_default_find self.bar_without_default_find || Bar.last end alias_method_chain :bar, :default_find 

这会创build两个方法bar_with_default_findbar_without_default_find以及别名到with方法。 这样,你可以明确地调用其中一个,或者保留默认值。

我发现使用“超级”是最好的方法

 def bar super || Bar.last end 

我希望这可以帮助你:D