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?

5voto

Magne Punkte 15365

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

Gibt es eine kanonische Methode zum Festlegen von Standardwerten für Felder in ActiveRecord-Modell zu setzen?

Die kanonische Rails Weg, vor Rails 5, war eigentlich um es in der Migration zu setzen, und schauen Sie einfach in der db/schema.rb für alle, die sehen wollen, welche Standardwerte von der DB für ein beliebiges Modell festgelegt wurden.

Im Gegensatz zu der Antwort von @Jeff Perrin (die schon etwas älter ist), wird der Migrationsansatz sogar den Standard anwenden, wenn Sie Model.new dank einiger Rails-Magie. Überprüft arbeiten in Rails 4.1.16.

Das Einfachste ist oft das Beste. Weniger Wissensdefizite und potenzielle Unklarheiten in der Codebasis. Und es "funktioniert einfach".

class AddStatusToItem < ActiveRecord::Migration
  def change
    add_column :items, :scheduler_type, :string, { null: false, default: "hotseat" }
  end
end

Oder, wenn Sie eine Spalte ändern wollen, ohne eine neue zu erstellen, dann tun Sie beides:

class AddStatusToItem < ActiveRecord::Migration
  def change
    change_column_default :items, :scheduler_type, "hotseat"
  end
end

Oder vielleicht noch besser:

class AddStatusToItem < ActiveRecord::Migration
  def change
    change_column :items, :scheduler_type, :string, default: "hotseat"
  end
end

Prüfen Sie die offizielle RoR-Leitfaden für Optionen in Spaltenänderungsmethoden.

En null: false verbietet NULL-Werte in der DB, und als zusätzlicher Vorteil werden auch alle bereits vorhandenen DB-Datensätze, die zuvor null waren, mit dem Standardwert für dieses Feld versehen. Sie können diesen Parameter bei der Migration ausschließen, wenn Sie möchten, aber ich fand ihn sehr praktisch!

Der kanonische Weg in Rails 5+ ist, wie @Lucas Caton sagte:

class Item < ActiveRecord::Base
  attribute :scheduler_type, :string, default: 'hotseat'
end

4voto

John Topley Punkte 110122

Dafür sind Konstrukteure da! Überschreiben Sie das Modell initialize Methode.

Verwenden Sie die after_initialize Methode.

4voto

Tony Punkte 49

Hallo Leute, ich habe das Folgende gemacht:

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

Funktioniert wie ein Zauber!

3voto

clem Punkte 3504

Diese Frage wurde schon lange beantwortet, aber ich brauche häufig Standardwerte und möchte sie nicht in die Datenbank eingeben. Ich erstelle eine DefaultValues betreffen:

module DefaultValues
  extend ActiveSupport::Concern

  class_methods do
    def defaults(attr, to: nil, on: :initialize)
      method_name = "set_default_#{attr}"
      send "after_#{on}", method_name.to_sym

      define_method(method_name) do
        if send(attr)
          send(attr)
        else
          value = to.is_a?(Proc) ? to.call : to
          send("#{attr}=", value)
        end
      end

      private method_name
    end
  end
end

Und dann verwende ich sie in meinen Modellen wie folgt:

class Widget < ApplicationRecord
  include DefaultValues

  defaults :category, to: 'uncategorized'
  defaults :token, to: -> { SecureRandom.uuid }
end

2voto

Sean Punkte 21

Ich hatte Probleme mit after_initialize Geben ActiveModel::MissingAttributeError Fehler bei der Durchführung komplexer Suchvorgänge:

z. B:

@bottles = Bottle.includes(:supplier, :substance).where(search).order("suppliers.name ASC").paginate(:page => page_no)

"Suche" in der .where ist ein Hash von Bedingungen

Also habe ich es so gemacht, indem ich initialize auf diese Weise überschrieben habe:

def initialize
  super
  default_values
end

private
 def default_values
     self.date_received ||= Date.current
 end

En super Aufruf ist notwendig, um sicherzustellen, dass das Objekt korrekt initialisiert wird von ActiveRecord::Base bevor ich meinen eigenen Code anpasse, d.h.: default_values

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