Ich versuche, den besten Weg zu finden, um Standardwerte für Objekte in Rails festzulegen.
Das Beste, was ich mir vorstellen kann, ist, den Standardwert in der new
Methode im Controller festzulegen.
Hat jemand eine Eingabe, ob dies akzeptabel ist oder ob es einen besseren Weg gibt, dies zu tun?
ruby-on-rails
ruby
biagidp
quelle
quelle
Antworten:
"Richtig" ist ein gefährliches Wort in Ruby. Es gibt normalerweise mehr als einen Weg, etwas zu tun. Wenn Sie wissen, dass Sie immer diesen Standardwert für diese Spalte in dieser Tabelle möchten, ist es am einfachsten, sie in einer DB-Migrationsdatei festzulegen:
Da ActiveRecord Ihre Tabellen- und Spalteneigenschaften automatisch erkennt, wird in jedem Modell, das es in einer Standard-Rails-App verwendet, derselbe Standard festgelegt.
Wenn Sie jedoch nur in bestimmten Fällen Standardwerte festlegen möchten - beispielsweise, dass es sich um ein geerbtes Modell handelt, das eine Tabelle mit anderen teilt -, können Sie dies beim Erstellen des Modellobjekts direkt in Ihrem Rails-Code tun:
Wenn Sie dann a
GenericPerson.new()
ausführen, wird das Attribut "Doe" immer hochgespielt, esPerson.new()
sei denn, Sie überschreiben es mit etwas anderem.quelle
.new
Klassenmethode aufgerufen werden. In der Diskussion dieses Blogposts über den direkten Aufruf von ActiveRecord ging es um Modellobjekte,.allocate
die mit vorhandenen Daten aus der Datenbank geladen wurden. ( Und es ist eine schreckliche Idee für ActiveRecord, so zu arbeiten, IMO. Aber das istchange_column_default :people, :last_name, nil
stackoverflow.com/a/1746246/483520change_column :people, :last_name, :string, default: "Doe"
Basierend auf der Antwort von SFEley ist hier eine aktualisierte / feste für neuere Rails-Versionen:
quelle
change_column
kann durchaus sein „Strukturierung“, kann der umgekehrte Vorgang nicht abgeleitet werden. Wenn Sie sich nicht sicher sind, testen Sie es einfach durch Ausführendb:migrate
unddb:rollback
direkt danach. Akzeptierte Antwort als gleiches Ergebnis, aber zumindest wird davon ausgegangen!up
unddown
wie oben beschrieben von @GoBustoErstens können Sie nicht überladen,
initialize(*args)
da es nicht in allen Fällen aufgerufen wird.Am besten geben Sie Ihre Standardeinstellungen in Ihre Migration ein:
Am zweitbesten ist es, Standardeinstellungen in Ihr Modell einzufügen. Dies funktioniert jedoch nur mit Attributen, die anfangs null sind. Möglicherweise haben Sie Probleme wie bei
boolean
Spalten:Du brauchst das
new_record?
damit die Standardeinstellungen die aus der Datenbank geladenen Werte nicht überschreiben.Sie müssen verhindern
||=
, dass Rails Parameter überschreibt, die an die Initialisierungsmethode übergeben werden.quelle
after_initiation :your_method_name
... 2 verwendenself.max_users ||= 10
after_initialize do
stattdef after_initialize
Sie können auch
change_column_default
Ihre Migrationen ausprobieren (getestet in Rails 3.2.8):change_column_default Rails-API-Dokumente
quelle
Wenn Sie sich auf ActiveRecord-Objekte beziehen, haben Sie (mehr als) zwei Möglichkeiten, dies zu tun:
1. Verwenden Sie einen: Standardparameter in der Datenbank
Z.B
Weitere Informationen hier: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
2. Verwenden Sie einen Rückruf
Z.B
before_validation_on_create
Weitere Informationen hier: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M002147
quelle
In Ruby on Rails v3.2.8 können Sie mithilfe des
after_initialize
ActiveRecord-Rückrufs eine Methode in Ihrem Modell aufrufen, die die Standardwerte für ein neues Objekt zuweist .Also, IMO sollte es ungefähr so aussehen:
Foo.bar = default_value
für diese Instanz, es sei denn, die Instanz enthält eineattribute_whose_presence_has_been_validated
zuvor beim Speichern / Aktualisieren. Dasdefault_value
wird dann in Verbindung mit Ihrer Ansicht verwendet, um das Formular mit demdefault_value
for-bar
Attribut zu rendern .Bestenfalls ist das hacky ...
BEARBEITEN - benutze 'new_record?' um zu überprüfen, ob ein neuer Anruf ausgelöst wurde
Verwenden Sie die
new_record?
integrierte Methode mit Schienen, anstatt einen Attributwert zu überprüfen . Das obige Beispiel sollte also so aussehen:Das ist viel sauberer. Ah, die Magie von Rails - es ist schlauer als ich.
quelle
after_initialize
hier einen Rückruf? Die Rails-Dokumentation zu Rückrufen enthält ein Beispiel für das Festlegen des Standardwertsbefore_create
ohne zusätzliche BedingungsprüfungenSubscription
after_initialize
anstelle desbefore_create
Rückrufs den verwenden, ist, dass wir beim Erstellen neuer Objekte einen Standardwert für den Benutzer (zur Verwendung in einer Ansicht) festlegen möchten . Derbefore_create
Rückruf wird aufgerufen, nachdem dem Benutzer ein neues Objekt zugestellt, seine Eingabe bereitgestellt und das Objekt zur Erstellung an die Steuerung gesendet wurde. Der Controller sucht dann nachbefore_create
Rückrufen. Es scheint nicht intuitiv zu sein, aber es ist eine Nomenklatursache -before_create
bezieht sich auf diecreate
Handlung. Das Instanziieren eines neuen Objekts führt nichtcreate
zum Objekt.Zumindest für boolesche Felder in Rails 3.2.6 funktioniert dies bei Ihrer Migration.
Das Setzen eines
1
oder0
für einen Standardwert funktioniert hier nicht, da es sich um ein boolesches Feld handelt. Es muss eintrue
oderfalse
Wert sein.quelle
Falls Sie mit einem Modell zu tun haben, können Sie die Attriutes API in Rails 5+ verwenden http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute
Fügen Sie einfach eine Migration mit einem richtigen Spaltennamen hinzu und legen Sie sie dann im Modell fest mit:
quelle
Eine Migration und Verwendung generieren
change_column_default
, ist prägnant und reversibel:quelle
Wenn Sie nur Standardeinstellungen für bestimmte Attribute eines datenbankgestützten Modells festlegen, würde ich die Verwendung von SQL-Standardspaltenwerten in Betracht ziehen. Können Sie klarstellen, welche Arten von Standardeinstellungen Sie verwenden?
Es gibt eine Reihe von Ansätzen, um damit umzugehen. Dieses Plugin scheint eine interessante Option zu sein.
quelle
Der Vorschlag, new / initialize zu überschreiben, ist wahrscheinlich unvollständig. Rails ruft (häufig) die Zuweisung für ActiveRecord-Objekte auf, und Aufrufe für die Zuweisung führen nicht zu Aufrufen zum Initialisieren.
Wenn Sie über ActiveRecord-Objekte sprechen, sehen Sie sich das Überschreiben von after_initialize an.
Diese Blog-Beiträge (nicht meine) sind nützlich:
Standardwerte Standardkonstruktoren werden nicht aufgerufen
[Bearbeiten: SFEley weist darauf hin, dass Rails tatsächlich die Standardeinstellung in der Datenbank überprüft, wenn ein neues Objekt im Speicher instanziiert wird - das hatte ich nicht bemerkt.]
quelle
Ich musste einen Standard festlegen, als wäre er als Standardspaltenwert in der Datenbank angegeben worden. So verhält es sich also
Da der Rückruf after_initialize nach dem Festlegen von Attributen aus Argumenten aufgerufen wird, konnte nicht festgestellt werden, ob das Attribut Null ist, da es nie oder absichtlich als Null festgelegt wurde. Also musste ich ein bisschen reinschauen und kam mit dieser einfachen Lösung.
Funktioniert super für mich. (Schienen 3.2.x)
quelle
Ein potenziell noch besserer / sauberer potenzieller Weg als die vorgeschlagenen Antworten besteht darin, den Accessor wie folgt zu überschreiben:
Siehe "Überschreiben von Standard-Accessoren" in der ActiveRecord :: Base-Dokumentation und mehr von StackOverflow zur Verwendung von self .
quelle
i beantworten eine ähnliche Frage hier .. eine saubere Art und Weise , dies zu tun ist mit Rails attr_accessor_with_default
AKTUALISIEREN
attr_accessor_with_default ist in Rails 3.2 veraltet. Sie können dies stattdessen mit reinem Ruby tun
quelle
attr_accessor_with_default
ist ab Schienen> 3.1.0 veraltetWenn Sie über ActiveRecord-Objekte sprechen, verwende ich das Juwel "Attribut-Standard".
Dokumentation und Download: https://github.com/bsm/attribute-defaults
quelle
Sie können das Juwel rails_default_value verwenden. z.B:
https://github.com/keithrowell/rails_default_value
quelle
Sie können den Konstruktor für das ActiveRecord-Modell überschreiben.
So was:
quelle