Rails: ActiveRecord でデフォルト値を設定するにはどうすればいいですか? 質問する

Rails: ActiveRecord でデフォルト値を設定するにはどうすればいいですか? 質問する

ActiveRecord でデフォルト値を設定するにはどうすればよいですか?

Pratik の投稿で、醜くて複雑なコードについて説明されているのを見ました。http://m.onkey.org/2007/7/24/モデル内のデフォルト値の設定方法

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

グーグルで検索してみると、次のような例が見つかりました。

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

そして

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

移行時にこれを組み込む人も見かけますが、モデル コードで定義する方がよいと思います。

ActiveRecord モデルのフィールドにデフォルト値を設定する標準的な方法はありますか?

ベストアンサー1

利用可能な各メソッドにはいくつかの問題がありますが、after_initialize次の理由から、コールバックを定義するのが最善の方法であると考えています。

  1. default_scope新しいモデルの値を初期化しますが、それがモデルを見つけるスコープになります。いくつかの数値を 0 に初期化したいだけであれば、これは望ましいことではありません。
  2. 移行時にデフォルトを定義することもできます (古いバージョンの Rails では、 を呼び出すだけでは機能しませModel.new)。
  3. オーバーライドはinitialize機能しますが、 を呼び出すことを忘れないでくださいsuper
  4. phusion のようなプラグインを使用するのは、ちょっとばかげています。これは Ruby ですが、デフォルト値を初期化するためだけにプラグインが本当に必要なのでしょうか?
  5. Rails 3 以降ではオーバーライドafter_initialize は非推奨です。Rails 3.0.3 でオーバーライドすると、after_initializeコンソールに次の警告が表示されます。

非推奨の警告: Base#after_initialize は非推奨になりました。代わりに Base.after_initialize :method を使用してください。(/Users/me/myapp/app/models/my_model:15 から呼び出されます)

したがって、次のように関連付けのデフォルトを設定できるだけでなく、after_initialize属性をデフォルト設定できるコールバックを作成することをお勧めします。

  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    

これで、モデルの初期化を探す場所は1 か所だけになりました。誰かがもっと良い方法を思いつくまで、私はこの方法を使っています。

注意:

  1. ブールフィールドの場合は次のようにします。

    self.bool_field = true if self.bool_field.nil?

    詳細については、この回答に対するポール・ラッセルのコメントを参照してください。

  2. モデルの列のサブセットのみを選択している場合 (つまり、selectのようなクエリで を使用している場合)、メソッドが 句に含まれていない列にアクセスすると がPerson.select(:firstname, :lastname).all発生します。次のようにして、このケースを防ぐことができます。MissingAttributeErrorinitselect

    self.number ||= 0.0 if self.has_attribute? :number

    ブール列の場合は...

    self.bool_field = true if (self.has_attribute? :bool_value) && self.bool_field.nil?

    また、Rails 3.2より前の構文は異なることに注意してください(下記のCliff Darlingのコメントを参照)。

おすすめ記事