2010-03-23 48 views
43

所以我知道如何使用轨道覆盖的关系(belongs_to的)默认的getter

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

我试图达到同样的事情,但是,对于一个属于覆盖默认的getter为一个ActiveRecord对象的属性协会。例如。

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 

然而,这总会让一个数据库调用,即使酒吧已经被取出,这肯定是不理想的。

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

回答

70

alias_method是你的朋友在这里。

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

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

+0

你不必与一个循环?因为酒吧里的通话吧? – shingara 2010-03-23 14:50:58

+0

不,你打电话给“酒吧”的新名称“original_bar”。 – 2010-03-23 15:08:28

+0

工作就像一个魅力!非常感谢 – brad 2010-03-23 19:45:39

10

兰迪的答案是当场就,但有把它写一个简单的方法,使用alias_method_chain:


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

这就产生了两个方法 - bar_with_default_findbar_without_default_find和别名barwith方法。通过这种方式,您可以明确地调用其中一个,或者按照原样保留默认值。

+0

很酷的解决方案,因为您可以使用'_without_default_find'来获得原始关联方法的概念。是我唯一能够工作的人。谢谢 – grant 2016-06-02 18:15:34

13

我发现,使用“超级”是,我希望最好的办法

def bar 
    super || Bar.last 
end 

这可以帮助你:d