Rotaie 6
Rails 6 ha aggiunto metodi upsert
e upsert_all
che forniscono questa funzionalità.
Model.upsert(column_name: value)
[upsert] Non istanzia alcun modello né attiva callback o convalide di Active Record.
Rotaie 5, 4 e 3
No, se stai cercando un tipo di istruzione "upsert" (dove il database esegue un aggiornamento o un'istruzione di inserimento nella stessa operazione). Fuori dagli schemi, Rails e ActiveRecord non hanno questa funzionalità. Tuttavia, puoi usare la gemma upsert .
Altrimenti, puoi usare: find_or_initialize_by
or find_or_create_by
, che offre funzionalità simili, anche se al costo di un ulteriore accesso al database, il che, nella maggior parte dei casi, non è affatto un problema. Quindi, a meno che tu non abbia seri problemi di prestazioni, non userei la gemma.
Ad esempio, se non viene trovato alcun utente con il nome "Roger", viene name
creata un'istanza di una nuova istanza utente con la relativa impostazione "Roger".
user = User.where(name: "Roger").first_or_initialize
user.email = "email@example.com"
user.save
In alternativa, puoi usare find_or_initialize_by
.
user = User.find_or_initialize_by(name: "Roger")
In Rails 3.
user = User.find_or_initialize_by_name("Roger")
user.email = "email@example.com"
user.save
Puoi usare un blocco, ma il blocco viene eseguito solo se il record è nuovo .
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
Se vuoi usare un blocco indipendentemente dalla persistenza del record, usa tap
sul risultato:
User.where(name: "Roger").first_or_initialize.tap do |user|
user.email = "email@example.com"
user.save
end