454 Stimmen

Geländer: Wie kann ich Standardwerte in ActiveRecord setzen?

Wie kann ich einen Standardwert in ActiveRecord festlegen?

Ich sehe einen Beitrag von Pratik, der ein hässliches, kompliziertes Stückchen Code beschreibt: http://m.onkey.org/2007/7/24/how-to-set-default-values-in-your-model

class Item < ActiveRecord::Base  
  def initialize_with_defaults(attrs = nil, &block)
    initialize_without_defaults(attrs) do
      setter = lambda { |key, value| self.send("#{key.to_s}=", value) unless
        !attrs.nil? && attrs.keys.map(&:to_s).include?(key.to_s) }
      setter.call('scheduler_type', 'hotseat')
      yield self if block_given?
    end
  end
  alias_method_chain :initialize, :defaults
end

Beim Herumgoogeln habe ich die folgenden Beispiele gesehen:

  def initialize 
    super
    self.status = ACTIVE unless self.status
  end

und

  def after_initialize 
    return unless new_record?
    self.status = ACTIVE
  end

Ich habe auch schon Leute gesehen, die es in ihre Migration eingebaut haben, aber ich würde es lieber im Modellcode definiert sehen.

Gibt es einen kanonischen Weg, um Standardwert für Felder in ActiveRecord-Modell festlegen?

1voto

Jeff Gran Punkte 1505

Das Problem mit den after_initialize-Lösungen ist, dass Sie ein after_initialize zu jedem einzelnen Objekt hinzufügen müssen, das Sie aus der DB abrufen, unabhängig davon, ob Sie auf dieses Attribut zugreifen oder nicht. Ich schlage einen lazy-loaded Ansatz vor.

Die Attributmethoden (Getter) sind natürlich selbst Methoden, so dass Sie sie überschreiben und einen Standardwert angeben können. Etwa so:

Class Foo < ActiveRecord::Base
  # has a DB column/field atttribute called 'status'
  def status
    (val = read_attribute(:status)).nil? ? 'ACTIVE' : val
  end
end

Es sei denn, Sie müssen, wie bereits erwähnt, Foo.find_by_status('ACTIVE') verwenden. In diesem Fall denke ich, dass Sie wirklich brauchen, um den Standard in Ihrer Datenbank Einschränkungen zu setzen, wenn die DB es unterstützt.

1voto

etipton Punkte 154

Ich empfehle dringend die Verwendung des Edelsteins "default_value_for": https://github.com/FooBarWidget/default_value_for

Es gibt einige knifflige Szenarien, die ein Überschreiben der Initialisierungsmethode erfordern, was dieser Edelstein tut.

Beispiele:

Ihr db-Standard ist NULL, Ihr model/ruby-defined Standard ist "some string", aber Sie haben tatsächlich wollen um den Wert aus irgendeinem Grund auf Null zu setzen: MyModel.new(my_attr: nil)

Bei den meisten Lösungen wird der Wert nicht auf null gesetzt, sondern auf den Standardwert.

OK, anstatt also die ||= Ansatz, wechseln Sie zu my_attr_changed? ...

BUT Stellen Sie sich nun vor, Ihre Datenbankvorgabe ist "some string", Ihre in Ruby definierte Vorgabe ist "some other string", aber in einem bestimmten Szenario müssen Sie wollen um den Wert auf "some string" (die db-Vorgabe) zu setzen: MyModel.new(my_attr: 'some_string')

Dies wird dazu führen, dass my_attr_changed? unter falsch weil der Wert mit der DB-Vorgabe übereinstimmt, die wiederum Ihren in Ruby definierten Standardcode auslöst und den Wert auf "eine andere Zeichenkette" setzt -- wiederum nicht das, was Sie wollten.


Aus diesen Gründen glaube ich nicht, dass dies mit einem after_initialize-Hook richtig erreicht werden kann.

Auch hier denke ich, dass das "default_value_for"-Gem der richtige Ansatz ist: https://github.com/FooBarWidget/default_value_for

1voto

Mike Breen Punkte 2560
class Item < ActiveRecord::Base
  def status
    self[:status] or ACTIVE
  end

  before_save{ self.status ||= ACTIVE }
end

1voto

Greg Punkte 4341

Die Methode after_initialize ist veraltet, verwenden Sie stattdessen den Callback.

after_initialize :defaults

def defaults
  self.extras||={}
  self.other_stuff||="This stuff"
end

jedoch mit :default in Ihren Migrationen ist immer noch der sauberste Weg.

0voto

skalee Punkte 11472

Obwohl dies für das Setzen von Standardwerten in den meisten Fällen verwirrend und umständlich ist, können Sie mit :default_scope auch. Ausprobieren squil's Kommentar hier .

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