ruby on rails - rails - los rieles anulan el getter predeterminado para una relación(belongs_to)
rails references (3)
Así que sé cómo anular los getters predeterminados para los atributos de un objeto ActiveRecord usando
def custom_getter
return self[:custom_getter] || some_default_value
end
Estoy tratando de lograr lo mismo, sin embargo, para un pertenece a la asociación. Por ejemplo.
class Foo < AR
belongs_to :bar
def bar
return self[:bar] || Bar.last
end
end
class Bar < AR
has_one :foo
end
Cuando yo digo:
f = Foo.last
Me gustaría que el método f.bar
devuelva la última barra, en lugar de nada si esa asociación aún no existe.
Esto no funciona sin embargo. La razón es que self [: bar] siempre está indefinido. En realidad es self [: bar_id].
Puedo hacer algo ingenuo como:
def bar
if self[:bar_id]
return Bar.find(self[:bar_id])
else
return Bar.last
end
end
Sin embargo, esto siempre hará una llamada db, incluso si ya se ha buscado Bar, lo que ciertamente no es ideal.
¿Alguien tiene una idea de cómo podría tener una relación tal que el atributo belongs_to solo se cargue una vez y tenga un valor predeterminado si no se establece?
La respuesta de Randy es acertada, pero hay una manera más fácil de escribirla, usando alias_method_chain:
def bar_with_default_find
self.bar_without_default_find || Bar.last
end
alias_method_chain :bar, :default_find
Eso crea dos métodos: bar_with_default_find
y bar_without_default_find
y alias bar
al método with
. De esta forma, puede llamar explícitamente a uno u otro, o simplemente dejar los valores predeterminados tal como están.
alias_method es tu amigo aquí.
alias_method :original_bar, :bar
def bar
self.original_bar || Bar.last
end
La forma en que esto funciona es que alias el método de "barra" predeterminado como "barra original" y luego implementa tu propia versión de "barra". Si la llamada a original_bar devuelve nil, entonces devuelve la última instancia de Bar.
encontré que usar "super" es la mejor manera
def bar
super || Bar.last
end
Espero que esto te ayude: D