2012-03-26 11 views
7

Quiero alterar un registro, pero no quiero leerlo primero en la base de datos, porque francamente no veo el punto. Es enorme y atraviesa una red que es lenta y costosa. ¿Se puede hacer (fácilmente)?¿Es posible alterar un registro en rieles, sin leerlo primero?

Digamos que tengo un registro con 100 campos (por razones de argumentos) y quiero alterar un campo de la tabla. Tengo una conexión realmente mala con la base de datos (esto es cierto) porque está alojada en un cuadro diferente y no hay nada que pueda hacer para cambiar esto. Ahora mismo despliegue el registro y los rieles validan su contenido (porque tengo bits serializados) Luego modifico un campo (uno de los cientos dependiendo de la condición X) y guardo el registro nuevamente. Lo cual supongo que vuelve a escribir todo el registro en la base de datos, sin conocimiento del hecho de que solo cambié un poco. (este último es supuesto)

Ahora para cambiar un registro que está enviando una gran cantidad de datos a través de la red, y podría ser que yo sólo estoy cambiando una pequeña cosa pequeña .. también lo está haciendo dos consultas en la base de datos. Primero seleccione * luego la actualización ..

Así que mi pregunta ... ¿hay clases base más inteligentes que lo hagan bien, para escribir sin leer?
En la parte superior de mi cabeza, creo que un método setter para cada campo con una bandera bool para cambiar. Al guardar, caminar por las banderas y donde sea cierto ... ¿Esto sucede ahora? Si es así, ¿cómo puedo usarlo?

+0

"(este último es un supuesto)": esa es una suposición falsa. ActiveRecord es lo suficientemente inteligente como para escribir solo los valores modificados. Ya cuenta con indicadores para realizar un seguimiento de los campos que cambiaron. –

+0

En realidad, mira los documentos para esto (llamados por cierto "Actualizaciones parciales") en realidad solo están en los rieles de borde y no están programados para ser lanzados hasta Rails 4. Puede haber un complemento o gema "actualizaciones parciales". –

+1

Sí, es una actualización inteligente. Y sobre hacer un hallazgo primero, si sabes lo que quieres actualizar, ¿no es encontrar un registro con su ID una operación de tiempo constante? ¿Qué tan grande puede ser el DB? – Shaunak

Respuesta

6

Los modelos de rieles tienen el método update, que selecciona SQL y luego actualiza SQL.

Su uso es sencillo (suponga que tiene un modelo llamado persona)

Person.update(person_id, :user_name => 'New Name') 

El inconveniente es que tienes que saber de antemano la ID de la persona.

Pero luego, siempre tendrá que hacer una consulta para averiguarlo. Puede escribir su propio SQL para cambiar el valor de la columna, con una cláusula WHERE que busca el parámetro que tiene.

Los modelos de rieles tienen el método update_all, que solo hace una actualización SQL sin cargar los datos. Pero no recomendaría su uso porque no desencadena devolución de llamada o validaciones que su modelo pueda tener.

podría utilizar el update_all así:

Book.update_all "author = 'David'", "title LIKE '%Rails%'" 

ps: ejemplos fueron tomados de la documentación oficial de los rieles. Si busca una actualización o update_all, encontrará ambos métodos en un instante.

Eche un vistazo allí, es un buen lugar para descubrir qué pueden hacer los rieles.

Rails API link

+0

Podría escribir mi propio sql, pero ¿por qué usar activerecord en absoluto eh? Gracias por esto. No estoy seguro de cómo crear uno que esté incluido en mi modelo. Mi vista y controlador no deberían saber qué está sucediendo, solo que están guardando. – baash05

+0

A veces tienes que escribir tus propias cosas, cuando tienes problemas muy específicos, créeme, jeje. Pero si su sitio no es algo enorme, con miles de accesos por minuto, ir a buscar solo el ID del archivo base está bien, use los métodos normales y solo preocúpese si realmente tiene una razón para hacerlo. Escuche las sabias palabras de Knuth: "La optimización prematura es la raíz de todo mal". – Castilho

+0

Gracias por la actualización .. Podría intentar usarlo en todos mis campos. Aún no estoy seguro de cómo. – baash05

2

No es obvio a partir de la documentación, pero update_all es la respuesta a esta pregunta.

Book.where(id: 123).update_all(title: "War and Peace") 

resultados en exactamente una consulta:

UPDATE `books` SET `books`.`title` = "War and Peace" WHERE `books`.`id` = 123 

Ha pasado un tiempo desde que esta pregunta fue hecha, pero esto es por lo que para Carriles 4.

Cuestiones relacionadas