Schienen 6
Rails 6 fügte ein upsert
und upsert_all
Methoden hinzu, die diese Funktionalität bereitstellen.
Model.upsert(column_name: value)
[upsert] Es werden weder Modelle instanziiert noch Active Record-Rückrufe oder -Validierungen ausgelöst.
Schienen 5, 4 und 3
Nicht, wenn Sie nach einem Anweisungstyp "Upsert" suchen (bei dem die Datenbank ein Update oder eine Insert-Anweisung in derselben Operation ausführt). Rails und ActiveRecord verfügen standardmäßig über keine solche Funktion. Sie können jedoch den Upsert- Edelstein verwenden.
Andernfalls können Sie Folgendes verwenden: find_or_initialize_by
oder find_or_create_by
, die ähnliche Funktionen bieten, allerdings auf Kosten eines zusätzlichen Datenbanktreffers, der in den meisten Fällen kaum ein Problem darstellt. Wenn Sie also keine ernsthaften Leistungsprobleme haben, würde ich den Edelstein nicht verwenden.
Wenn beispielsweise kein Benutzer mit dem Namen "Roger" gefunden wird, wird eine neue Benutzerinstanz mit der name
Einstellung "Roger" instanziiert .
user = User.where(name: "Roger").first_or_initialize
user.email = "email@example.com"
user.save
Alternativ können Sie verwenden find_or_initialize_by
.
user = User.find_or_initialize_by(name: "Roger")
In Schienen 3.
user = User.find_or_initialize_by_name("Roger")
user.email = "email@example.com"
user.save
Sie können einen Block verwenden, der Block wird jedoch nur ausgeführt, wenn der Datensatz neu ist .
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
Wenn Sie einen Block unabhängig von der Persistenz des Datensatzes verwenden möchten, verwenden Sie tap
für das Ergebnis:
User.where(name: "Roger").first_or_initialize.tap do |user|
user.email = "email@example.com"
user.save
end