Szyny 6
Railsy 6 dodały metody upsert
i upsert_all
, które zapewniają tę funkcjonalność.
Model.upsert(column_name: value)
[upsert] Nie tworzy instancji żadnych modeli ani nie wyzwala wywołań zwrotnych ani walidacji modułu Active Record.
Szyny 5, 4 i 3
Nie, jeśli szukasz typu instrukcji „upsert” (gdzie baza danych wykonuje aktualizację lub instrukcję wstawiania w tej samej operacji). Po wyjęciu z pudełka, Railsy i ActiveRecord nie mają takiej funkcji. Możesz jednak użyć górnego klejnotu.
W przeciwnym razie możesz użyć: find_or_initialize_by
lub find_or_create_by
, które oferują podobną funkcjonalność, jednak kosztem dodatkowego trafienia do bazy danych, co w większości przypadków nie stanowi żadnego problemu. Więc jeśli nie masz poważnych problemów z wydajnością, nie użyłbym tego klejnotu.
Na przykład, jeśli nie zostanie znaleziony żaden użytkownik o nazwie „Roger”, tworzona jest instancja nowego użytkownika z name
ustawieniem „Roger”.
user = User.where(name: "Roger").first_or_initialize
user.email = "email@example.com"
user.save
Alternatywnie możesz użyć find_or_initialize_by
.
user = User.find_or_initialize_by(name: "Roger")
W Railsach 3.
user = User.find_or_initialize_by_name("Roger")
user.email = "email@example.com"
user.save
Możesz użyć bloku, ale blok działa tylko wtedy, gdy rekord jest nowy .
User.where(name: "Roger").first_or_initialize do |user|
user.save
end
User.find_or_initialize_by(name: "Roger") do |user|
user.save
end
Jeśli chcesz użyć bloku niezależnie od trwałości rekordu, użyj tap
na wyniku:
User.where(name: "Roger").first_or_initialize.tap do |user|
user.email = "email@example.com"
user.save
end