¡Las diferencias entre .build, .create y .create! y cuando deberían ser utilizados?

167

Así que he estado viendo a la gente que usa .build, .createy.create! dentro de sus controladores más y más últimamente. ¿Cuál es la diferencia de usar .newy pasar el objeto param'd y luego .save? ¿Hay pros y contras? ¿El uso de estos otros métodos ofrece beneficios?

Tim Knight
fuente

Respuestas:

234

Hay un par de diferencias, pero no son grandes:

  1. .createes equivalente a .newseguido por .save. Es solo más sucinto.
  2. .create!es equivalente a .newseguido de .save!(arroja un error si falla el guardado). También es solo un poquito más corto
  3. Creo que .buildes sobre todo un alias para .new. Se trabaja de una manera en los carriles 3 y de otra en los carriles <3.x

Sin embargo, la parte más importante es que estos métodos pueden llamarse a través de una asociación ( has_many, etc.) para vincular automáticamente los dos modelos.

zenazn
fuente
1
He seleccionado esta como la respuesta más correcta debido a la mención de poder vincular los modelos asociados con ellos; esa es una diferencia interesante e importante que pienso sobre usar .new y .save. Lo que requiere un poco de trabajo extra. Gracias.
Tim Knight
11
Aclaración menor sobre 3: la compilación hace un poco más que una novedad: también establece el enlace de asociación.
Two Bit Gangster
116
Build es diferente de New. Pero la diferencia no es que establece el enlace de asociación (Nuevo también lo hace para la nueva instancia). La diferencia es que Build llena a la persona que llama con la nueva instancia, pero New no. Entonces, por ejemplo: Wall.posts.new le ofrece una nueva publicación asociada con su muro, pero Wall.posts todavía está vacía después de esta llamada. Wall.posts.build te ofrece una nueva publicación asociada a tu muro, y tus Wall.posts ahora tienen una publicación.
Amin Ariana
3
¿No es solo un alias ahora, sin una funcionalidad especial?
Gabriele Cirulli
14
En Rails 4, acabo de registrarme en la consola. wall.posts.new y wall.posts.build están poblando el objeto de la pared exactamente de la misma manera. Significa después de wall.posts.new, wall.posts no está vacío como se afirma en el comentario de Amin.
Bot
35

Aunque es correcto que createllama newy luego savehay una gran diferencia entre las dos alternativas en sus valores de retorno.

Savedevuelve trueo falsedependiendo de si el objeto se guardó correctamente en la base de datos o no. Esto se puede usar para el control de flujo según el primer ejemplo en la pregunta anterior.

Createdevolverá el modelo independientemente de si el objeto se guardó o no. Esto tiene implicaciones para el código anterior en que la rama superior de laif instrucción siempre se ejecutará, incluso si el objeto falla las validaciones y no se guarda.

Si usa la createlógica de ramificación, corre el riesgo de fallas silenciosas, lo que no es el caso si usa new+ save.

create! no sufre el mismo problema que plantea y una excepción si el registro no es válido.

La createalternativa puede ser útil en controladores donde respond_withse usa para respuestas API (JSON / XML). En este caso, la existencia de errores en el objeto hará que los errores se devuelvan en la respuesta con un estado de unprocessable_entity, que es exactamente lo que desea de una API.

Siempre usaría la opción new+ savepara html, especialmente si confía en el valor de retorno para el control de flujo.

nmott
fuente
6

#create es una versión más corta de new y save. #¡crear! está lanzando una excepción si la validación no fue positiva.

rkj
fuente
5

En segundo lugar, las respuestas anteriores. Además create, no se puede pasar falsecomo argumento con el que se puede hacer save. Pasar falsecomo argumento omitirá todas las validaciones de rieles

Vineeth Pradhan
fuente