2011-02-28 12 views
11

En una aplicación RoR, quiero especializar el método update_attributes() de ActiveRecord en uno de mis modelos, extraer algunos de los atributos para un manejo especial y pasar el resto al método original update_attributes(). Los detalles:Ruby/RoR: llamando al método original a través de super()?

class Premise < ActiveRecord::Base 
    ... 
    def update_attributes(attrs) 
    attrs.each_pair do |key, val| 
     unless has_attribute?(key) 
     do_special_processing(key, val) 
     attrs.delete(key) 
     end 
    end 
    # use original update_attributes() to process non-special pairs 
    super.update_attributes(attrs) 
    end 
    ... 
end 

La llamada a super.update_attributes (ATTR) genera un error:

undefined method `update_attributes' for true:TrueClass 

... lo que me hace sospechar que realmente no entiendo la palabra clave super en Ruby. ¿Qué me estoy perdiendo? Específicamente, ¿cómo llamo al método original update_attributes()?

Respuesta

15

que desee:

super(attrs) 

que llamará al método original, pasando attrs como un argumento a la misma.

Como está ahora, intenta llamar a update_attributes sobre el valor "verdadero" devuelto por la actualización_attributes original.

+4

En este caso, los argumentos sobre 'update_attributes (attrs)' y 'super (attrs)' son los mismos. Simplemente puede llamar a 'super', sin paréntesis. –

+0

@LBg Ah, gracias, buen punto. También corregí un poco al final de mi respuesta sobre eso; Originalmente escribí que el código en la pregunta se llamaba update_attributes sin argumentos, pero eso no es correcto. – DSimon

+0

Bingo - gracias. Mi pasado como programador de Java se muestra a través de ... –

4

Esto se parece a un mejor uso para alias_method_chain:

def update_attributes_with_special(attrs) 
    attrs.each_pair do |key, val| 
    unless has_attribute?(key) 
     do_special_processing(key, val) 
     attrs.delete(key) 
    end 
    end 
    update_attributes_without_special(attrs) 
end 
alias_method_chain :update_attributes, :special 
+0

Lo contemplé. Eso nos lleva a la siguiente pregunta: ¿cuándo harías una subclase y cuándo encadenas? –

+0

@FearlessFool: la herencia suele ser un olor codificado en Ruby sin un argumento convincente para el estado/recursos internos compartidos. El beneficio de usar la cadena alias_method es comer tu pastel y tenerlo también. Obtiene una clase con una actualización de atributos_actualizados() y también conserva la funcionalidad no modificada. – Winfield

35

En Rubí Super es un caso especial en el paréntesis no importa ...

Calling super sin parámetros (ni paréntesis) en un método de una subclase llama al mismo método en la superclase (o sus antecesores si la superclase no lo define) con todos los parámetros pasados ​​al método de la subclase. Entonces, aquí, podrías haber escrito simplemente super.

Calling super() llama al método de la superclase (o antepasados) sin ningún parámetro (suponiendo que este método no acepta parámetros ...)

Calling super(...) con cualquier combinación de parámetros llama al método de la superclase, pasándole los parametros

+0

Hombre esto es súper útil. ¿Qué tal enviar explícitamente los mismos parámetros recibidos y el método es 'method (param, * otherargs)'? – unmultimedio

Cuestiones relacionadas