1. ホーム
  2. ruby-on-rails

[解決済み] Railsです。ActiveRecordでデフォルト値を設定するにはどうすればよいですか?

2022-03-22 10:23:12

質問

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

Pratikからの投稿を見ると、醜く複雑なコードの塊が書かれています。 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

ググってみると、以下のような例がありました。

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

そして

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

マイグレーションに入れる人も見かけますが、私はむしろモデルコードで定義してほしいです。

ActiveRecordのモデルでフィールドにデフォルト値を設定する正規の方法はありますか?

どのように解決するのですか?

利用できる方法にはそれぞれいくつかの問題がありますが、私は after_initialize コールバックは、次のような理由から、この方法が望ましいと思います。

  1. default_scope は新しいモデルのために値を初期化しますが、その後、それはモデルを見つけるためのスコープになります。もし、いくつかの数値を0に初期化したいだけなら、これは ではなく ということです。
  2. マイグレーションでデフォルトを定義することも一部では有効ですが...。すでに述べたように、これは ない は、Model.new を呼び出しただけでは動作しません。
  3. オーバーライド initialize を使用することができます。 super !
  4. phusionのようなプラグインを使うのは、ちょっとバカバカしくなってきましたね。これはrubyです。いくつかのデフォルト値を初期化するためだけにプラグインが必要なのでしょうか?
  5. オーバーライド after_initialize は非推奨 は、Rails 3 の時点では をオーバーライドすると after_initialize をrails 3.0.3で使用すると、コンソールに以下のような警告が表示されます。

DEPRECATION WARNING: Base#after_initialize は非推奨です。代わりに Base.after_initialize :メソッドを使用してください。(/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. ブーリアンフィールドの場合、以下のようにします。

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

    詳しくは、この回答に対するPaul Russellのコメントをご覧ください。

  2. モデルのカラムのサブセットのみを選択する場合 (たとえば select のようなクエリで Person.select(:firstname, :lastname).all ) を取得することになります。 MissingAttributeError もし init メソッドに含まれていないカラムにアクセスします。 select 節があります。この場合、次のようにガードすることができます。

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

    そして、booleanカラムの場合...

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

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