rails 覆盖关系的默认 getter (belongs_to)
Posted
技术标签:
【中文标题】rails 覆盖关系的默认 getter (belongs_to)【英文标题】:rails override default getter for a relationship (belongs_to) 【发布时间】:2011-01-30 20:12:40 【问题描述】:所以我知道如何使用
覆盖 ActiveRecord 对象的属性的默认 getterdef 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
方法返回最后一个 Bar,而不是 nil。
但这不起作用。原因是 self[:bar] 总是未定义的。实际上是 self[:bar_id]。
我可以做一些幼稚的事情,比如:
def bar
if self[:bar_id]
return Bar.find(self[:bar_id])
else
return Bar.last
end
end
然而,这总是会进行 db 调用,即使 Bar 已经被获取,这当然不理想。
有没有人了解我如何建立这样的关系,即 belongs_to 属性只加载一次,如果未设置则具有默认值。
【问题讨论】:
【参考方案1】:alias_method 是你的朋友。
alias_method :original_bar, :bar
def bar
self.original_bar || Bar.last
end
其工作方式是将默认的“bar”方法别名为“original bar”,然后实现自己的“bar”版本。如果对 original_bar 的调用返回 nil,那么您将返回最后一个 Bar 实例。
【讨论】:
你没有那个循环吗?因为在 bar 中调用 bar ? 不,你叫“original_bar”,这是“bar”的新名称。 一件事让我很头疼,就是要记住在新的别名方法之前调用 alias_method 第 3 行不能只是original_bar || Bar.last
更好:super || Bar.last
【参考方案2】:
我发现使用“super”是最好的方法
def bar
super || Bar.last
end
希望对你有帮助:D
【讨论】:
这是一个很好的答案,因为它只是使用普通的旧 Ruby 继承。而且它比公认的答案要简单得多。【参考方案3】:Randy 的答案是正确的,但有一种更简单的方法来编写它,使用 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_find
和 bar_without_default_find
并将 bar
别名为 with
方法。这样您就可以显式调用其中一个,或者保留默认值。
【讨论】:
很酷的解决方案,因为您可以使用_without_default_find
来了解原始关联方法的概念。是我唯一能够开始工作的人。谢谢
我相信alias_method_chain
现在已被弃用。【参考方案4】:
基于此处的其他答案,您可能还想处理分配操作。
别名方法:
alias_method :original_bar, :bar
alias_method :original_bar=, :bar=
def bar
self.original_bar ||= Bar.last
end
超级方法:
def bar
super || bar = Bar.last
end
这对我有用的地方是在使用 Bar.find_or_initialize_by
时,这意味着记录并不总是持久化,而且任何非持久化的更改也会反映在父记录上。
【讨论】:
这并没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review 我的答案与已接受的解决方案具有相同的逻辑,但对其进行了扩展以进行分配操作。以上是关于rails 覆盖关系的默认 getter (belongs_to)的主要内容,如果未能解决你的问题,请参考以下文章