2009-11-05 6 views
13

tal vez algunos expertos en ruby ​​puedan arrojar algo de luz sobre cómo activerecord sabe hacer una inserción o actualización al llamar a save(). ¿Cuál es la lógica detrás de esto? ¿Comprueba si la clave principal está en blanco o algo así y, de ser así, una inserción, si no es una actualización?¿cómo sabe activerecord realizar una inserción o actualización?

+0

Excelente pregunta. –

Respuesta

23

Mientras que está bien para algunas personas que dicen "RTFM" Yo más bien la más recorrido, pero-aún-entirely- inútiles-when-Rails-3-viene-hacia fuera-y-cambios-todo la respuesta:

Cómo funciona en Rails 2.3 (también conocido como "hoy")

save llama create_or_update que se parece a esto:

def create_or_update 
    raise ReadOnlyRecord if readonly? 
    result = new_record? ? create : update 
    result != false 
end 

Puede pasar por alto la primera línea de este método, ya que sólo genera un error si el registro es de sólo lectura (no es por lo general, pero en el caso de combinaciones que pueda ser) . Lo que nos interesa aquí es la segunda y tercera líneas dentro del método.

La segunda línea llama new_record? que se define como esto:

# Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet; otherwise, returns false. 
    def new_record? 
    @new_record || false 
    end 

Y la variable @new_record se establece cuando el initialize (new llamadas initialize, y nos da un nuevo objeto, algunos antecedentes Rubí-fu aquí) método se llama.

Así que si esto es @new_recordtrue que van a llamar create y si es falso que llamaré a update que nos lleva a lo que está buscando, creo.

Además, cuando encuentra un registro, no llama al initialize y, por lo tanto, no establece @new_record. Si se dio cuenta, el código detrás de new_record? fue @new_record || false, lo que significa que devolverá falso si no se configuró @new_record.

Digamos, por ejemplo, que desea encontrar el último registro Forum, por lo que haría Forum.last.

  1. Esto llama al método last en la clase Forum, que hereda de ActiveRecord :: Base
  2. lastcalls el método de clase find.
  3. findcallsfind_last
  4. find_lastcallsfind_initial
  5. find_initialcallsfind_every
  6. find_everycallsfind_by_sql
  7. find_by_sql y llamadas instantiate

Verá aquí que en ninguna parte a lo largo de este cambio se establece @new_record y, por lo tanto, cualquier registro obtenido por find no será un nuevo registro.

Espero que esto te ayude a entender.

+0

muy buena respuesta y creo que por el tiempo que tomó para que lo escriba. También me interesa saber qué establecería @nw_record en falso. ¿Realizaría un hallazgo hacer eso si extrae un registro de la base de datos? – rip747

+0

He actualizado la publicación con la cadena de métodos Find. –

+0

¿Hay alguna forma de modificar el atributo "new_record" usted mismo? –

1

Consulte el doc de activerecord here y el código fuente there.

+0

He estado leyendo los documentos y el código y no puedo entenderlo. – rip747

+0

Usted también está enlazando con el maestro. Probablemente esté usando 2.3. –

2

Principally se basa en el método new_record?.
Este método devuelve verdadero si es un registro nuevo y falso si no lo es.

De hecho, no es realmente difícil.

  • Cuando obtiene un registro existente, no es nuevo. Entonces new_record? puede devolver falso de forma directa.
  • Cuando crea un nuevo registro (Model.new), new_record? devolverá verdadero. Es un nuevo disco.
  • Cuando guarda ese nuevo registro, ya no es nuevo. La variable interna @new_record se actualiza. new_record? ya no volverá a ser verdadero.

Para ver cuando sucede, vaya a ActiveRecord::Base, línea 2911

self.id ||= new_id 

    @new_record = false 
    id 
    end 
+0

Vas a vincular al maestro cuando probablemente esté usando 2.3. –

+0

Eso no cambia mi argumento. Pero he actualizado el enlace de todos modos. –

Cuestiones relacionadas