references rails inverse_of has_and_belongs_to_many foreign belong association ruby-on-rails activerecord associations default-value

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