2008-12-17 8 views
143

un ejemplo de lo que estoy hablando:reemplazar los métodos de atributos ActiveRecord

class Person < ActiveRecord::Base 
    def name=(name) 
    super(name.capitalize) 
    end 
    def name 
    super().downcase # not sure why you'd do this; this is just an example 
    end 
end 

Esto parece funcionar, pero se acaba de leer la sección sobre sustitución métodos de atributos en el ActiveRecord::Base docs, y se sugiere el uso de la read_attribute y write_attribute métodos. Pensé que debe haber algo mal con lo que estoy haciendo en el ejemplo anterior; de lo contrario, ¿por qué bendecirían estos métodos como la "forma correcta" de anular los métodos de los atributos? También están forzando un modismo mucho más feo, por lo que debe haber una buena razón ...

Mi pregunta real: ¿Hay algún problema con este ejemplo?

Respuesta

199

Haciéndose eco de los comentarios de Gareth ... su código no funcionará como está escrito. Se debe reescribirse así:

def name=(name) 
    write_attribute(:name, name.capitalize) 
end 

def name 
    read_attribute(:name).downcase # No test for nil? 
end 
+0

Exactamente lo que necesitaba. Gracias Aaron. – bong

+15

Esto ya no es cierto. O súper o esto funciona ahora. Sin embargo, no he probado la notación hash. – tehgeekmeister

+2

En rails 3, el método de lector especificado aquí por Aaron funciona, pero el escritor que especificó el póster original (que introduce el nombre en súper) funciona bien, y en mi humilde opinión es más limpio que escribir manualmente el atributo como sugiere Aaron. – Batkins

88

Como una extensión de la respuesta de Aaron Longwell, también se puede utilizar una "notación de hash" a atributos de acceso que han anulado descriptores de acceso y mutadores:

def name=(name) 
    self[:name] = name.capitalize 
end 

def name 
    self[:name].downcase 
end 
+0

La notación hash puede funcionar, pero 'self.attribute' sopla la pila en 3.2.16. – jrhorn424

+0

Esto tiene la ventaja de que admite '|| =' para el valor predeterminado: 'def name; self [: nombre] || = 'anon'; end' –

-1

tengo un complemento de rieles que hace que la anulación de atributos funcione con super como es de esperar. Puede encontrarlo en github.

Para instalar:

./script/plugin install git://github.com/chriseppstein/has_overrides.git 

de usar:

class Post < ActiveRecord::Base 

    has_overrides 

    module Overrides 
    # put your getter and setter overrides in this module. 
    def title=(t) 
     super(t.titleize) 
    end 
    end 
end 

Una vez que usted ha hecho que las cosas funcionan:

$ ./script/console 
Loading development environment (Rails 2.3.2) 
>> post = Post.new(:title => "a simple title") 
=> #<Post id: nil, title: "A Simple Title", body: nil, created_at: nil, updated_at: nil> 
>> post.title = "another simple title" 
=> "another simple title" 
>> post.title 
=> "Another Simple Title" 
>> post.update_attributes(:title => "updated title") 
=> true 
>> post.title 
=> "Updated Title" 
>> post.update_attribute(:title, "singly updated title") 
=> true 
>> post.title 
=> "Singly Updated Title" 
+3

Esto ya está incorporado a los rieles – ramn

Cuestiones relacionadas