426 Stimmen

Rails update_attributes ohne speichern?

Gibt es eine Alternative zu update_attributes der den Datensatz nicht speichert?

Ich könnte also etwas tun wie:

@car = Car.new(:make => 'GMC')
#other processing
@car.update_attributes(:model => 'Sierra', :year => "2012", :looks => "Super Sexy, wanna make love to it")
#other processing
@car.save

Übrigens, ich weiß, ich kann @car.model = 'Sierra' aber ich möchte sie alle in einer Zeile aktualisieren.

655voto

Ajedi32 Punkte 40666

Ich glaube, was Sie suchen, ist assign_attributes .

Es ist im Grunde dasselbe wie update_attributes, aber es speichert den Datensatz nicht:

class User < ActiveRecord::Base
  attr_accessible :name
  attr_accessible :name, :is_admin, :as => :admin
end

user = User.new
user.assign_attributes({ :name => 'Josh', :is_admin => true }) # Raises an ActiveModel::MassAssignmentSecurity::Error
user.assign_attributes({ :name => 'Bob'})
user.name        # => "Bob"
user.is_admin?   # => false
user.new_record? # => true

207voto

Yarin Punkte 157128

Sie können verwenden assign_attributes o attributes= (sie sind identisch)

Methoden-Spickzettel aktualisieren (für Rails 6):

  • update = assign_attributes + save
  • attributes= = Alias von assign_attributes
  • update_attributes = veraltet, Alias von update

Quelle:
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_assignment.rb

Ein weiterer Spickzettel:
http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet

68voto

bbonamin Punkte 28942

Sie können die Methode "Attribute" verwenden:

@car.attributes = {:model => 'Sierra', :years => '1990', :looks => 'Sexy'}

Quelle: http://api.rubyonrails.org/classes/ActiveRecord/Base.html

attributes=(new_attributes, guard_protected_attributes = true) Ermöglicht es, alle Attribute auf einmal zu setzen, indem ein Hash mit Schlüsseln übergeben wird, die mit den Attributnamen übereinstimmen (die wiederum mit den Spaltennamen übereinstimmen).

Wenn guard_protected_attributes true ist (Standardeinstellung), können sensible Attribute vor dieser Form der Massenzuweisung mit dem Makro attr_protected geschützt werden. Alternativ kann man mit dem Makro attr_accessible festlegen, auf welche Attribute zugegriffen werden darf. Dann dürfen alle Attribute, die nicht in diesem Makro enthalten sind, nicht massenweise zugewiesen werden.

class User < ActiveRecord::Base
  attr_protected :is_admin
end

user = User.new
user.attributes = { :username => 'Phusion', :is_admin => true }
user.username   # => "Phusion"
user.is_admin?  # => false

user.send(:attributes=, { :username => 'Phusion', :is_admin => true }, false)
user.is_admin?  # => true

9voto

Michael Gaskill Punkte 7728

Für die Massenzuweisung von Werten zu einem ActiveRecord-Modell ohne Speichern verwenden Sie entweder die assign_attributes o attributes= Methoden. Diese Methoden sind in Rails 3 und neueren Versionen verfügbar. Es gibt jedoch geringfügige Unterschiede und versionsbedingte Probleme, die zu beachten sind.

Beide Methoden folgen dieser Verwendung:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }

@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }

Beachten Sie, dass keine der beiden Methoden Überprüfungen durchführt oder Rückrufe ausführt; Rückrufe und Überprüfungen werden durchgeführt, wenn save genannt wird.

Schiene 3

attributes= unterscheidet sich leicht von assign_attributes in Rails 3. attributes= prüft, ob das übergebene Argument ein Hash ist, und gibt sofort zurück, wenn dies nicht der Fall ist; assign_attributes hat keine solche Hash-Prüfung. Siehe die ActiveRecord-Attribut-Zuordnung API-Dokumentation für attributes= .

Der folgende ungültige Code schlägt fehl, indem er einfach zurückkehrt, ohne die Attribute zu setzen:

@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]

attributes= verhält sich stillschweigend so, als seien die Zuweisungen erfolgreich durchgeführt worden, obwohl dies in Wirklichkeit nicht der Fall war.

Dieser ungültige Code wird eine Ausnahme auslösen, wenn assign_attributes versucht, die Hash-Schlüssel des umschließenden Arrays zu stringifizieren:

@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])

assign_attributes wird eine NoMethodError Ausnahme für stringify_keys und zeigt damit an, dass das erste Argument kein Hash ist. Die Ausnahme selbst ist nicht sehr informativ über die tatsächliche Ursache, aber die Tatsache, dass eine Ausnahme auftritt, ist très wichtig.

Der einzige Unterschied zwischen diesen Fällen ist die Methode der Massenzuordnung: attributes= gelingt stillschweigend, und assign_attributes löst eine Ausnahme aus, um zu informieren, dass ein Fehler aufgetreten ist.

Diese Beispiele mögen konstruiert erscheinen, und das sind sie bis zu einem gewissen Grad auch, aber diese Art von Fehler kann leicht auftreten, wenn man Daten aus einer API konvertiert oder auch nur eine Reihe von Datentransformationen verwendet und vergisst, die Hash[] die Ergebnisse der Abschlussprüfung .map . Pflegen Sie einen Code, der 50 Zeilen höher und 3 Funktionen von Ihrer Attributzuweisung entfernt ist, und Sie haben ein Rezept für einen Fehlschlag.

Die Lektion mit Rails 3 ist diese: immer utilice assign_attributes anstelle von attributes= .

Schienen 4

In Rails 4, attributes= ist einfach ein Alias für assign_attributes . Siehe die ActiveRecord-Attribut-Zuordnung API-Dokumentation für attributes= .

Mit Rails 4 können beide Methoden austauschbar verwendet werden. Wird kein Hash als erstes Argument übergeben, führt dies zu einer sehr hilfreichen Ausnahme: ArgumentError: When assigning attributes, you must pass a hash as an argument.

Validierungen

Wenn Sie Aufgaben zur Vorbereitung auf eine Flugreise erledigen save können Sie auch die Validierung vor dem Speichern in Betracht ziehen. Sie können die valid? y invalid? Methoden dafür. Beide geben boolesche Werte zurück. valid? gibt true zurück, wenn das nicht gespeicherte Modell alle Validierungen besteht, oder false, wenn es nicht besteht. invalid? ist einfach der Kehrwert von valid?

valid? kann wie folgt verwendet werden:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?

Dies gibt Ihnen die Möglichkeit, alle Validierungsprobleme vor dem Aufruf von save .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X