2012-02-01 43 views
6

Estoy tratando de actualizar un campo usando update_all. Sin embargo, necesito que se tome el valor de otro campo que se vuelve a escribir en mi formato específico.Usando el método Rails update_all para actualizar campos con valor de otra columna

Si tengo algo como esto en mi modelo:

def self.clean_mac_address() 
    clean_mac_address = :macaddress.gsub(/[^0-9a-z]/i, '') 
end 

Cuando ejecuto esto:

Radacct.update_all("mac_clean = #{clean_mac_address}") 

me sale un error:

NoMethodError: undefined method `gsub' for :macaddress:Symbol 

¿Alguna idea de cómo puedo ¿hacer esto? ¿O hay una manera más simple de actualizar el campo?

+1

Dudo si se puede usar método '' gsub' en un symbol'. Puede ser esa es la razón por la que está recibiendo un error. – uday

+1

Primero, ¿por qué llamas 'gsub' a un símbolo? Segundo, si entiendo correctamente, quiere calcular y llenar la columna 'mac_clean' basada en otra columna para cada registro. En ese caso, puede usar 'update_all' solo si realiza toda la manipulación en SQL ya que' update_all' ejecutará la actualización que le está pasando como una cadena en todos los registros, pero no los cargará de DB y ganó ' t inicializar instancias de modelo. Eso significa que está tratando con consultas SQL y no tiene acceso directo a los atributos 'ActiveRecord'. –

+0

@ KL7: no se supone que macaddress sea un símbolo; debe ser una cadena. Entonces, ¿tengo que escribir algo para recorrer cada registro y actualizar? Estoy un poco confundido – simonmorley

Respuesta

11

update_all genera una sola consulta SQL para ejecutar; no puede hacer cosas inteligentes como cambiar bits arbitrarios de ruby ​​en SQL equivalente.

O lo que tenga que cargar todo lo que los casos (a través de find_each por ejemplo) y los fijan uno a uno (es decir, no utilice update_all), por ejemplo

Foo.find_each do |foo| 
    # update foo here 
    foo.save! 
end  

o encontrar una manera de expresar que la limpieza operación en SQL. Por ejemplo Postgres tiene una función regexp_replace

Foo.update_all("some_column = regexp_replace(some_column, 'your_regexp_here', '','g')") 

que eliminaría todo lo que la sustitución de expresiones regulares. Obviamente, deberá verificar la documentación de su base de datos para ver si es compatible con dicha función.

+0

¿Debo pegar esto en un bucle para encontrar el registro A, reemplazar el valor, moverme, etc.? ¿Puedes compartir un código? S – simonmorley

+0

Depende de cuál de las 2 formas en que te sugerí que elijas –

+0

Ok, miro adentro. Estoy en mysql. S – simonmorley

0

Mientras que la respuesta aceptada, proporciona una buena manera de update_all, lo que haría uso es

read_with_clean_addr = Radacct.where(mac_clean: :macaddress.gsub(/[^0-9a-z]/i, '')) 
read_with_clean_add.update_all(mac_clean: "#{clean_mac_address}") 
Cuestiones relacionadas