2011-04-09 14 views
13

En un modelo ActiveRecord::Base, que puede restablecer el estado del modelo de lo que era cuando lo tengo de la base de datos con reload, siempre y cuando el atributo Soy la creación de mapas para una columna de tabla:¿Hay una API limpia para restablecer las variables de instancia en 'volver a cargar' en ActiveRecord?

user = User.first 
user.email #=> "[email protected]" 
user.email = "[email protected]" 
user.email #=> "[email protected]" 
user.reload 
user.email #=> "[email protected]" 

Pero si añado un atributo personalizado, la única forma que he encontrado que tienen que actuar de la misma es la siguiente:

class User < ActiveRecord::Base 
    attr_accessor :user_agent 

    def reload 
    super 
    self.user_agent = nil 
    self 
    end 
end 

Mi pregunta es, ¿hay alguna API para hacer bases de datos no-columna-atributos reiniciar al volver a cargar? Algo como:

class User < ActiveRecord::Base 
    # this 
    reloadable_attr_accessor :user_agent 
    # or this 
    def user_agent 
    @user_agent 
    end 

    def user_agent=(value) 
    set_instance_var_that_resets_on_reload("@user_agent", value) 
    end 
end 

¿Existe eso en Rails?

+0

+1. Ojalá el equipo de los raíles proporcione una forma más clara de conectar los atributos virtuales en los modelos de vida AR. Tal vez podríamos sugerirles que lo hagan? Realmente podía ver una macro 'virtual_attribute', que se ocuparía de los problemas de recarga y la suciedad. –

Respuesta

12

ActiveRecord no proporciona una forma de hacerlo, solo puede actuar sobre los atributos del modelo.

Dicho esto, creo que una forma más elegante de hacerlo sería para recorrer los Ivars y ponerlos a lo que quiera:

class User < ActiveRecord::Base 
    def reload(options = nil) 
    super 
    self.instance_variables.each do |ivar| 
     next if ivar == '@attributes' 
     self.instance_variable_set(ivar, nil)  
    end 
    end 
end 

Tenga en cuenta que nos saltamos porque @attributes AR es cuidar de eso cuando recarga los atributos.

+2

¡Gracias por el consejo! Pero también hace que todas las asociaciones sean nulas :( – ep3static

+0

reelaborado un poco. Consulte mi respuesta a continuación. – gayavat

+0

no proporciona una manera no tan fea de restablecer todos los atributos?: / –

3

Rehaga la respuesta de Jean-Do levemente. No rompe las variables y las relaciones de instancia predeterminadas.

after_initialize do 
    @default_instance_variables = instance_variables 
end 

def reload(options = nil) 
    super 
    self.instance_variables.each do |ivar| 
    if ivar == :'@default_instance_variables' || 
     @default_instance_variables.include?(ivar) 
     next 
    end 
    remove_instance_variable(ivar) 
    end 
    self 
end 
1

Tomé la respuesta de gayavat y vuelto a trabajar en mi archivo test_helper.rb, porque no quiero reemplazar el método #reload habitual.

class ActiveRecord::Base 
    attr_accessor :default_instance_variables 
    after_initialize do 
    @default_instance_variables = instance_variables 
    end 
end 
def reload_ivars(obj) 
    obj.reload 
    obj.instance_variables.each do |ivar| 
    if ivar == :'@default_instance_variables' || 
    obj.default_instance_variables.include?(ivar) 
     next 
    end 
    obj.send(:remove_instance_variable, ivar) 
    end 
end 

cuando necesito para recargar algo en una prueba acabo de llamar reload_ivars(object).

Cuestiones relacionadas