Carriles 6
Rails 6 agregó métodos upsert
y upsert_all
que brindan esta funcionalidad.
Model.upsert(column_name: value)
[upsert] No crea instancias de ningún modelo ni activa devoluciones de llamada o validaciones de Active Record.
Carriles 5, 4 y 3
No si está buscando un tipo de declaración "upsert" (donde la base de datos ejecuta una actualización o una declaración de inserción en la misma operación). Fuera de la caja, Rails y ActiveRecord no tienen tal característica. Sin embargo, puedes usar la gema upsert .
De lo contrario, puede usar: find_or_initialize_by
o find_or_create_by
, que ofrecen una funcionalidad similar, aunque a costa de un acceso adicional a la base de datos, lo que, en la mayoría de los casos, no es un problema en absoluto. Entonces, a menos que tenga serias preocupaciones de rendimiento, no usaría la gema.
Por ejemplo, si no se encuentra ningún usuario con el nombre "Roger", se name
crea una instancia de una nueva instancia de usuario con su conjunto en "Roger".
user = User.where(name: "Roger").first_or_initialize
user.email = "email@example.com"
user.save
Alternativamente, puede usar find_or_initialize_by
.
user = User.find_or_initialize_by(name: "Roger")
En rieles 3.
user = User.find_or_initialize_by_name("Roger")
user.email = "email@example.com"
user.save
Puede usar un bloque, pero el bloque solo se ejecuta si el registro es nuevo .
User.where(name: "Roger").first_or_initialize do |user|
# this won't run if a user with name "Roger" is found
user.save
end
User.find_or_initialize_by(name: "Roger") do |user|
# this also won't run if a user with name "Roger" is found
user.save
end
Si desea usar un bloque independientemente de la persistencia del registro, use tap
en el resultado:
User.where(name: "Roger").first_or_initialize.tap do |user|
user.email = "email@example.com"
user.save
end