2010-03-23 24 views
43

así que sé cómo reemplazar los captadores por defecto para los atributos de un objeto ActiveRecord utilizandorieles prevalece sobre captador por defecto para una relación (belongs_to)

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

que estoy tratando de lograr lo mismo sin embargo, para una pertenece a 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 digo:

f = Foo.last 

me gustaría tener el método f.bar devolver el último bar, en vez de nil si esa asociación no existe todavía.

Esto no funciona, sin embargo. La razón es que self [: bar] siempre está indefinido. En realidad es self [: bar_id].

puedo hacer algo ingenua como:

def bar 
    if self[:bar_id] 
    return Bar.find(self[:bar_id]) 
    else 
    return Bar.last 
    end 
end 

Sin embargo, esto siempre va a hacer una llamada db, aunque bar ya ha sido exagerado, que por cierto no es lo ideal.

¿Alguien tiene una idea de cómo podría tener una relación tal que el atributo belongs_to solo se carga una vez y tiene un valor predeterminado si no se establece?

Respuesta

70

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 por defecto "barra" como "barra original" y luego poner en marcha su propia versión de "barra". Si la llamada a original_bar devuelve nil, entonces devuelve la última instancia de Bar.

+0

Usted no tiene un bucle con eso? porque la barra de llamadas en la barra? – shingara

+0

No, usted llama "original_bar" que es el nuevo nombre de "barra". –

+0

funcionó como un encanto! Muchas gracias – brad

10

respuesta de Randy es perfecto, pero hay una manera más fácil de escribir, 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.

+0

Solución genial porque puede usar '_without_default_find' para tener una noción del método de asociación original. Fue el único en el que pude trabajar. Gracias – grant

13

He encontrado que el uso de "super" es la mejor manera

def bar 
    super || Bar.last 
end 

espero que esto le ayuda a: D

Cuestiones relacionadas