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 protected]"
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 protected]"
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 protected]"
user.save
end
find_or_initialize_by
undfind_or_create_by
einen Block akzeptieren. Ich dachte, Sie haben gemeint, dass unabhängig davon, ob der Datensatz vorhanden ist oder nicht, ein Block mit dem Datensatzobjekt als Argument übergeben wird, um die Aktualisierung durchzuführen.In Rails 4 können Sie einem bestimmten Modell hinzufügen:
und benutze es gerne
Oder wenn Sie diese Methoden lieber allen Modellen hinzufügen möchten, die in einen Initialisierer eingefügt wurden:
quelle
assign_or_new
die erste Zeile in der Tabelle nicht zurückgegeben, wenn sie vorhanden ist, und diese Zeile wird dann aktualisiert? Es scheint das für mich zu tun.User.where(email: "[email protected]").first
wird nil zurückgeben, wenn nicht gefunden. Stellen Sie sicher , dass Sie eine habenwhere
Umfangupdated_at
die nicht berührt wird, weilassign_attributes
verwendet wirdFügen Sie dies Ihrem Modell hinzu:
Damit können Sie:
quelle
Die Magie, nach der Sie gesucht haben, wurde hinzugefügt.
Rails 6
Jetzt können Sie sie aktualisieren (aktualisieren oder einfügen). Für die Verwendung einzelner Datensätze:Verwenden Sie für mehrere Datensätze upsert_all :
Hinweis :
quelle
Alte Frage, aber der Vollständigkeit halber meine Lösung in den Ring werfen. Ich brauchte dies, wenn ich einen bestimmten Fund brauchte, aber einen anderen, wenn er nicht existiert.
quelle
Sie können dies in einer Anweisung wie folgt tun:
quelle
Das Fortsetzung- Juwel fügt eine update_or_create- Methode hinzu, die genau das zu tun scheint, wonach Sie suchen.
quelle