Rails 6
Rails 6 a ajouté un upsert
y upsert_all
qui fournissent cette fonctionnalité.
Model.upsert(column_name: value)
[Il n'instancie aucun modèle et ne déclenche aucun rappel ou validation d'Active Record.
Rails 5, 4 et 3
Pas si vous recherchez une instruction de type "upsert" (lorsque la base de données exécute une mise à jour ou une insertion au cours de la même opération). Rails et ActiveRecord ne disposent pas d'une telle fonctionnalité. Vous pouvez utiliser la fonction upsert un joyau, cependant.
Sinon, vous pouvez utiliser : find_or_initialize_by
ou find_or_create_by
qui offrent une fonctionnalité similaire, mais au prix d'un accès supplémentaire à la base de données, ce qui, dans la plupart des cas, n'est guère un problème. Donc, à moins que vous n'ayez de sérieux problèmes de performances, je n'utiliserais pas la gemme.
Par exemple, si aucun utilisateur n'est trouvé avec le nom "Roger", une nouvelle instance d'utilisateur est instanciée avec son nom name
est réglé sur "Roger".
user = User.where(name: "Roger").first_or_initialize
user.email = "email@example.com"
user.save
Alternativement, vous pouvez utiliser find_or_initialize_by
.
user = User.find_or_initialize_by(name: "Roger")
Dans Rails 3.
user = User.find_or_initialize_by_name("Roger")
user.email = "email@example.com"
user.save
Vous pouvez utiliser un bloc, mais le bloc ne s'exécute que si l'enregistrement est nouveau .
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 vous voulez utiliser un bloc indépendamment de la persistance de l'enregistrement, utilisez tap
sur le résultat :
User.where(name: "Roger").first_or_initialize.tap do |user|
user.email = "email@example.com"
user.save
end