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?

0voto

Bad Request Punkte 3930

Wenn es sich bei der Spalte um eine Spalte vom Typ "Status" handelt und sich Ihr Modell für die Verwendung von Zustandsautomaten eignet, sollten Sie die Option aasm gem Danach können Sie einfach Folgendes tun

  aasm column: "status" do
    state :available, initial: true
    state :used
    # transitions
  end

Es initialisiert immer noch nicht den Wert für ungespeicherte Datensätze, aber es ist etwas sauberer, als wenn Sie Ihre eigenen mit init oder was auch immer, und Sie profitieren von den anderen Vorteilen von aasm, wie z. B. den Bereichen für alle Ihre Status.

0voto

Keith Rowell Punkte 1

https://github.com/keithrowell/rails_default_value

class Task < ActiveRecord::Base
  default :status => 'active'
end

0voto

Kelvin Punkte 18752

Ich habe festgestellt, dass die Verwendung einer Validierungsmethode eine Menge Kontrolle über die Festlegung von Standardwerten bietet. Sie können sogar Standardwerte (oder eine fehlende Validierung) für Aktualisierungen festlegen. Sie können sogar einen anderen Standardwert für Einfügungen als für Aktualisierungen festlegen, wenn Sie das wirklich wollen. Beachten Sie, dass der Standardwert nicht gesetzt wird, bis #valid? aufgerufen wird.

class MyModel
  validate :init_defaults

  private
  def init_defaults
    if new_record?
      self.some_int ||= 1
    elsif some_int.nil?
      errors.add(:some_int, "can't be blank on update")
    end
  end
end

Bezüglich der Definition einer after_initialize-Methode könnte es zu Leistungsproblemen kommen, da after_initialize auch von jedem Objekt aufgerufen wird, das von :find zurückgegeben wird: http://guides.rubyonrails.org/active_record_validations_callbacks.html#after_initialize-and-after_find

0voto

kdweber89 Punkte 1700

Hier ist eine Lösung, die ich verwendet habe und von der ich überrascht war, dass sie noch nicht hinzugefügt wurde.

Sie besteht aus zwei Teilen. Der erste Teil ist die Festlegung des Standards in der eigentlichen Migration, und der zweite Teil ist das Hinzufügen einer Validierung im Modell, um sicherzustellen, dass das Vorhandensein wahr ist.

add_column :teams, :new_team_signature, :string, default: 'Welcome to the Team'

Hier sehen Sie, dass der Standardwert bereits eingestellt ist. In der Validierung wollen Sie nun sicherstellen, dass es immer einen Wert für die Zeichenkette gibt, also machen Sie einfach

 validates :new_team_signature, presence: true

Dadurch wird der Standardwert für Sie festgelegt. (bei mir ist das "Willkommen im Team"), und dann geht es noch einen Schritt weiter und stellt sicher, dass immer ein Wert für dieses Objekt vorhanden ist.

Ich hoffe, das hilft!

0voto

shilovk Punkte 9225
# db/schema.rb
create_table :store_listings, force: true do |t|
  t.string :my_string, default: "original default"
end

StoreListing.new.my_string # => "original default"

# app/models/store_listing.rb
class StoreListing < ActiveRecord::Base
  attribute :my_string, :string, default: "new default"
end

StoreListing.new.my_string # => "new default"

class Product < ActiveRecord::Base
  attribute :my_default_proc, :datetime, default: -> { Time.now }
end

Product.new.my_default_proc # => 2015-05-30 11:04:48 -0600
sleep 1
Product.new.my_default_proc # => 2015-05-30 11:04:49 -0600

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