Rails – ¿Cuál es un mejor enfoque para guardar actualizaciones de modelos?

He encontrado que ambos métodos funcionan para guardar datos. ¿Hay una ventaja de usar un método sobre el otro? ¿Cuáles son las ventajas / desventajas?

Primera versión:

begin @user.save! render json: "User #{@user.email} added", status: :created rescue StandardError => e render json: @user.errors.full_messages, status: :unprocessable_entity end 

Segunda versión:

  if @user.valid? @user.save! render json: "User #{@user.email} added", status: :created else render json: @user.errors.full_messages, status: :unprocessable_entity end 

Se trata de rendimiento. Su primer enfoque es más costoso porque la stack de llamadas completa debe desenrollarse para construir los detalles de la excepción y ni siquiera la usa.

Las excepciones son caras

Cuando se detecta una excepción, la excepción tiene el seguimiento completo de la stack donde ocurrió exactamente el error y cuál fue la secuencia de llamadas a métodos que condujeron a ese evento. La construcción de esta información requiere que Ruby pase a la llamada del método anterior y luego a la llamada del método anterior a la anterior, y así sucesivamente. Esta es una operación bastante costosa y como ya está dentro del método, realmente no necesita esta información.

Validar dos veces no es necesario

Entonces, de tus dos enfoques, la segunda versión es mejor. Sin embargo, la respuesta de jvperrin es aún mejor. En su segundo enfoque, usted llama @user.isvalid? que recorre todas las validaciones del modelo. Y cuando llama a @user.save , vuelve a pasar por las mismas validaciones. En su lugar, simplemente puede llamar a @user.save directamente y ver el valor de retorno, que es true cuando todo salió bien y false cuando hubo errores de validación.

Espero que ayude.

Me gustaría ir con una tercera alternativa, porque en guardar, el modelo se valida automáticamente:

 if @user.save render json: "User #{@user.email} added", status: :created else render json: @user.errors.full_messages, status: :unprocessable_entity end 

Puedes usar así

 if @user.valid? if @user.save! render json: "User #{@user.email} added", status: :created else render json: @user.errors.full_messages, status: :unprocessable_entity end else ##some code end 

Porque si el usuario no es válido no hay necesidad de entrar en guardar bloque.

¿No podría simplemente agregar validaciones a su modelo de usuario como una tercera alternativa más simple?

Algo como,

 class User < Activerecord::Base validates :email, presence: true end