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?

16voto

Milan Novota Punkte 15296

Die Jungs von Phusion haben einige schöne Plugin für diese.

10voto

staxim Punkte 951

Rails 6.1+

Sie können nun die Attribut Methode auf Ihr Modell anwenden, ohne einen Typ festzulegen.

attribute :status, default: ACTIVE

oder

class Account < ApplicationRecord
  attribute :locale, default: 'en'
end

Beachten Sie, dass die Eingabe einer Vorgabe für attribute kann nicht auf die Instanz der Klasse verweisen (ein Lambda wird im Kontext der Klasse ausgeführt, nicht der Instanz). Wenn Sie also den Standardwert dynamisch auf der Grundlage der Instanz oder der Assoziationen festlegen müssen, müssen Sie eine Alternative verwenden, wie z. B. eine after_initialize Rückruf. Wie bereits erwähnt, empfiehlt es sich, dies nur auf neue Datensätze zu beschränken, um n+1 Abfragen zu vermeiden, wenn Sie auf Zuordnungen verweisen.

after_initialize :do_something_that_references_instance_or_associations, if: :new_record?

9voto

peterhurford Punkte 1034

Eine noch bessere/sauberere Möglichkeit als die vorgeschlagenen Antworten ist es, den Accessor zu überschreiben, etwa so:

def status
  self['status'] || ACTIVE
end

Siehe "Überschreiben von Standard-Accessoren" in die ActiveRecord::Base Dokumentation y mehr von StackOverflow zur Verwendung von self .

8voto

aidan Punkte 8816

Ich benutze die attribute-defaults gem

Aus der Dokumentation: ausführen. sudo gem install attribute-defaults und hinzufügen require 'attribute_defaults' zu Ihrer App.

class Foo < ActiveRecord::Base
  attr_default :age, 18
  attr_default :last_seen do
    Time.now
  end
end

Foo.new()           # => age: 18, last_seen => "2014-10-17 09:44:27"
Foo.new(:age => 25) # => age: 25, last_seen => "2014-10-17 09:44:28"

8voto

Blair Anderson Punkte 18077

Ähnliche Fragen, aber alle haben einen etwas anderen Kontext: - Wie erstelle ich einen Standardwert für Attribute im Rails activerecord-Modell?

Beste Antwort: Das hängt davon ab, was Sie wollen!

Wenn Sie wollen, dass jedes Objekt mit einem Wert beginnen: verwenden. after_initialize :init

Sie wollen die new.html Formular beim Öffnen der Seite einen Standardwert haben soll, verwenden Sie https://stackoverflow.com/a/5127684/1536309

class Person < ActiveRecord::Base
  has_one :address
  after_initialize :init

  def init
    self.number  ||= 0.0           #will set the default value only if it's nil
    self.address ||= build_address #let's you set a default association
  end
  ...
end 

Wenn Sie wollen, dass jedes Objekt haben einen aus Benutzereingaben berechneten Wert: verwenden. before_save :default_values Sie möchten, dass der Benutzer Folgendes eingibt X y luego Y = X+'foo' ? verwenden:

class Task < ActiveRecord::Base
  before_save :default_values
  def default_values
    self.status ||= 'P'
  end
end

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