Рельсы переопределяют по умолчанию getter для отношения (принадлежит_to)
Итак, я знаю, как переопределить получатели по умолчанию для атрибутов объекта ActiveRecord, используя
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
возвращал последнюю строку, а не nil, если эта связь еще не существует.
Однако это не работает. Причина в том, что self [: bar] всегда undefined. Это на самом деле 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 возвращает nil, тогда вы возвращаете последний экземпляр Bar.
Ответ 2
я обнаружил, что использование "супер" - лучший способ
def bar
super || Bar.last
end
Надеюсь, это поможет вам: D
Ответ 3
Ответ Рэнди на месте, но есть более простой способ написать его, используя 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
. Таким образом, вы можете явно вызвать тот или другой, или просто оставить значения по умолчанию как есть.