2010-04-28 6 views
12

Tengo un método before_save que llamo que cambia el nombre de una imagen cargada.Rieles: ¿Cómo ejecuto un before_save solo si se cumplen ciertas condiciones?

before_save :randomize_file_name 

def randomize_file_name 
    extension = File.extname(screen_file_name).downcase 
    key = ActiveSupport::SecureRandom.hex(8) 
    self.screen.instance_write(:file_name, "#{key}#{extension}") 
end 

Ese método es parte de mi modelo Item.

Eso funciona muy bien cuando creo un nuevo elemento o necesito actualizar la imagen asociada a un elemento ... pero el problema es que si necesito actualizar un elemento pero NO la imagen, el método randomize_file_name aún se ejecuta y cambia el nombre del archivo en la base de datos (aunque no el archivo en sí, obviamente).

Así que, estoy pensando que necesito encontrar una manera de ejecutar solo randomize_file_name si se incluye un archivo en el envío del formulario ... pero no estoy seguro de cómo hacerlo.

Respuesta

12

Use dirty objects.

before_save :randomize_file_name 

def randomize_file_name 
    # assuming the field that holds the name 
    # is called screen_file_name 
    if screen_file_name_changed? 
    extension = File.extname(screen_file_name).downcase 
    key = ActiveSupport::SecureRandom.hex(8) 
    self.screen.instance_write(:file_name, "#{key}#{extension}") 
    end 
end 
+0

Documentación más detallada aquí: http://apidock.com/rails/ActiveRecord/Dirty –

+1

Esto tampoco lo conseguirá. ¿Qué sucede si el usuario carga un nuevo archivo con el mismo nombre de archivo? En este caso, el nombre del archivo será el mismo, pero es posible que desee una clave diferente. –

0

Simplemente haga una comprobación rápida en la parte superior de la función y regrese si no necesita hacer nada.

def randomize_file_name 
    return unless screen_file_name # or whatever check you need to do 
    extension = File.extname(screen_file_name).downcase 
    key = ActiveSupport::SecureRandom.hex(8) 
    self.screen.instance_write(:file_name, "#{key}#{extension}") 
end 

Edición después de comentario:

Usted puede utilizar el objeto sucio como se ha mencionado por Simone Carletti, o puede ser creativo.

En el modelo:

attr_accessor :some_random_field_name_for_you_to_rename 

def randomize_file_name 
    return unless some_random_field_name_for_you_to_rename 
    extension = File.extname(screen_file_name).downcase 
    key = ActiveSupport::SecureRandom.hex(8) 
    self.screen.instance_write(:file_name, "#{key}#{extension}") 
end 

En la forma:

<%= f.hidden_field :some_random_field_name_for_you_to_rename, :value => "1" %> 
+0

Pero el problema es que si el formulario no contiene una carga, simplemente saca "screen_file_name" de la base de datos para esa identificación ... Necesito verificar específicamente si el envío del formulario incluye cualquier cosa para el campo de imagen ... y no sé cómo hacerlo desde el modelo. – Shpigford

1

seguir adelante y hacer que su método before_save llama en cada parada, sino como un primer paso en el método que ahora están teniendo llama "antes de guardar" debe tener una condición if que pruebe el caso específico que necesita.

4
before_save :randomize_file_name 

def randomize_file_name 
    if screen_file_name 
    extension = File.extname(screen_file_name).downcase 
    key = ActiveSupport::SecureRandom.hex(8) 
    return self.screen.instance_write(:file_name, "#{key}#{extension}") unless !screen_changed? 
    end 
end 

Esto comprueba si el archivo ha cambiado. Funciona el 90% del tiempo

Cuestiones relacionadas