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


417

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モデルのフィールドにデフォルト値を設定する標準的な方法はありますか?


自分で質問に回答したように見えますが、2つの異なるバリエーションがあります:)
Adam Byrtek '30年

19
「self.status」が「self.status」|| =「ACTIVE」でない限り、「self.status = ACTIVE」の「標準」Rubyイディオム
Mike Woodhouse

1
Jeff Perrinの回答は、現在承認済みとしてマークされているものよりもはるかに優れています。default_scopeは、クエリの動作も変更するという大きな副作用があるため、デフォルト値を設定するための受け入れられないソリューションです。
ローレンス、2011年


2
この質問に対するすべての賛成票を考えると、RubyにはActiveRecordのsetDefaultValueメソッドが必要だと思います
spartikus

回答:


557

使用可能な各メソッドにはいくつかの問題がありafter_initializeますが、次の理由により、コールバックを定義する方法が適していると思います。

  1. default_scope新しいモデルの値を初期化しますが、それがモデルを見つけるスコープになります。いくつかの数値を0に初期化したいだけなら、これはあなたが望むものではありません。
  2. マイグレーションでのデフォルトの定義も一部の時間で機能します...すでに述べたように、Model.newを呼び出しただけで機能しません。
  3. オーバーライドinitializeは機能しますが、呼び出すことを忘れないでくださいsuper
  4. phusionのようなプラグインを使用することは少しばかげています。これはルビーですが、いくつかのデフォルト値を初期化するためだけに本当にプラグインが必要ですか?
  5. オーバーライドafter_initialize Rails 3で廃止されました。rails3.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?

    詳細については、この回答に関するPaul Russellのコメントを参照してください

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

    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のコメントを参照)。


7
これは間違いなくこれを達成するための最良の方法のようです。これは本当に奇妙で残念です。作成時にモデル属性のデフォルトを確立するための賢明な推奨メソッドは、Railsにすでに組み込まれているはずの方法のようです。をオーバーライドする他の(信頼できる)方法は、initialize明確で明確に定義する必要があるものについては本当に複雑です。この機能はすでにどこかにあると想定していて、気付かなかったため、ここを検索する前にドキュメントを何時間もクロールしました。
seaneshbaugh

106
これに関する1つのメモ-デフォルトにするブールフィールドがある場合はself.bool_field ||= true、明示的にfalseに初期化してもフィールドがtrueに強制されるため、実行しないでください。代わりにself.bool_field = true if self.bool_field.nil?
ポールラッセル

2
ポイント#2に関して、Model.newは実際には、マイグレーションで定義されたデフォルトと連携して、またはより正確にはテーブル列のデフォルト値と連携して機能します。しかし、after_initializeコールバックに基づくJeffのメソッドがおそらく最良の方法であることを認識しています。ただ質問:それはダーティであるが保存されていないオブジェクトで動作しますか?あなたの例では、Person.new.number_wasは0.0を返しますか?
Laurent Farcy

21
この方法と、アクティブなレコードを持つ特定の列の選択を組み合わせて使用​​する場合の注意。この場合、クエリで指定された属性のみがオブジェクトで見つかり、初期化コードはをスローしMissingAttributeErrorます。次のように、追加のチェックを追加でき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+です。以前のバージョンではself.attributes.has_key?、を使用し、シンボルではなく文字列を使用する必要があります。
クリフダーリン

6
アソシエーションでこれを行うと、ルックアップ時にそれらのアソシエーションを積極的にロードします。まずinitializereturn if !new_record?パフォーマンスの問題を回避します。
カイルメイシー

68

Rails 5以降

モデル内で属性メソッドを使用できます。例:

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

defaultパラメータにラムダを渡すこともできます。例:

attribute :uuid, UuidType.new, default: -> { SecureRandom.uuid }

3
これは私が探していた宝石です!defaultもprocを取ることができます。たとえば、default:-> {Time.current.to_date}
schpet

1
タイプを2番目の引数として指定してください。指定しない場合、タイプはValueタイプキャストになり、タイプキャストは行われません。
null

嬉しいことに、これはstore_accessorでも機能しstore_accessor :my_jsonb_column, :localeます。たとえば、次のように定義できますattribute :locale, :string, default: 'en'
Ryan Romanchuk '30

ああ、それは素晴らしいです。フォームに表示するためにデフォルトが必要でしたが、これはうまくいきました。ルーカスに感謝します。
ポールワトソン

これらをに設定できnilます。それらがnilDB not null+ DBデフォルト+ github.com/sshaw/keep_defaultsにできない場合は、私の経験から行く方法です
sshaw

47

移行を通じてデフォルト値をデータベースに入れます( :default各列の定義でオプションを Active Recordがこれらの値を使用して各属性のデフォルトを設定できるようにします。

私見、このアプローチはARの原則に沿っています:設定より規約、DRY、テーブルの定義がモデルを駆動し、その逆ではありません。

デフォルトは、モデルではなく移行ではありますが、アプリケーション(Ruby)コードにまだあることに注意してください。


3
別の問題は、外部キーのデフォルト値が必要な場合です。ID値が外部キーフィールドにハードコード化できないのは、DBによってIDが異なる可能性があるためです。
shmichael

2
さらに別の問題は、この方法では非永続的なアクセサー(db列ではない属性)を初期化できないことです。
ViktorTrón、

2
もう1つの問題は、すべてのデフォルト値を1か所に表示できるとは限らないことです。それらは、さまざまなマイグレーションによって分散する可能性があります。
デクラン

8
デクラン、db / schema.rbがある
ベンジャミンアトキン

6
私は将来の読者に言及したいと思います:少なくとも私が読んだことから、これはARの原則に反しています。モデルのロジックはモデルクラス内にある必要があり、データベースはできるだけ無知である必要があります。私にとってのデフォルト値は、モデルに関する特定のロジックを構成します。
darethas 2013

40

いくつかの単純なケースは、データベーススキーマでデフォルトを定義することで処理できますが、計算された値や他のモデルのキーなど、より複雑なケースは処理できません。これらの場合、私はこれを行います:

after_initialize :defaults

def defaults
   unless persisted?
    self.extras||={}
    self.other_stuff||="This stuff"
    self.assoc = [OtherModel.find_by_name('special')]
  end
end

after_initializeを使用することにしましたが、新規または作成されたオブジェクトのみが検出されるオブジェクトに適用したくありません。この明らかな使用例にafter_newコールバックが提供されていないことはほとんど衝撃的だと思いますが、オブジェクトが既に永続化されているかどうかを確認して、新しいものではないことを確認しました。

ブラッド・マレーの答えを見たので、条件がコールバック要求に移されれば、これはさらにきれいです:

after_initialize :defaults, unless: :persisted?
              # ":if => :new_record?" is equivalent in this context

def defaults
  self.extras||={}
  self.other_stuff||="This stuff"
  self.assoc = [OtherModel.find_by_name('special')]
end

4
これは本当に重要なポイントです。ほとんどの場合、レコードのデフォルトの設定は、永続化されたレコードをロードするときではなく、新しいレコードを永続化する前にのみ行われることを想像しなければなりません。
Russell Silva

やあ、あなたは私の日を救った。
stephanfriedrich

2
いかが:before_createですか?
フランクリン・ユー

:before_createはどのように個別の新規呼び出しと保存呼び出しを処理しますか?それに切り替える前に、それを確認して本当に理解したいと思います。
ジョセフ卿

17

after_initializeコールバックパターンは、以下を実行するだけで改善できます。

after_initialize :some_method_goes_here, :if => :new_record?

次のコードは、関連付けられたものを含めずに最初のレコードを読み取った場合に微妙なn + 1をトリガーするため、initコードで関連付けを処理する必要がある場合、これは重要なメリットがあります。

class Account

  has_one :config
  after_initialize :init_config

  def init_config
    self.config ||= build_config
  end

end

16

Phusionの人たちは、このための素晴らしいプラグインを持っています


このプラグインを使用すると:default、スキーマ移行の値をで「そのまま使用」できますModel.new
jchook 14

ジェフが彼の投稿で言ったこと:defaultModel.newは逆に、マイグレーションの値を「で動作する」ようにすることができます。Rails 4.1.16での動作を確認。
マグネ

8

提案された回答よりも優れた/よりクリーンな潜在的な方法は、次のようにアクセサーを上書きすることです:

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

ActiveRecord :: Baseのドキュメントの「デフォルトアクセサーの上書き」およびselfの使用に関するStackOverflowの詳細を参照してください。


から返されるハッシュでは、ステータスはnilのままattributesです。レール5.2.0でテスト済み。
2018年

8

宝石を使うattribute-defaults

ドキュメントから:実行してアプリにsudo gem install attribute-defaults追加require 'attribute_defaults'します。

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"

7

同様の質問ですが、すべてのコンテキストが少し異なります。- Railsのactiverecordのモデルで属性のデフォルト値を作成するにはどうすればよいですか?

ベストアンサー:何をしたいかに依存します!

すべてのオブジェクトを値で開始する場合:使用after_initialize :init

あなたはしたいnew.htmlフォームがページを開いたときにデフォルト値を持っていますか?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 

すべてのオブジェクトにユーザー入力から計算された値持たせたい場合 Usebefore_save :default_values you want to enterXthen thenY = X+'foo'?使用する:

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

4

これがコンストラクターの目的です!モデルのinitializeメソッドをオーバーライドします。

after_initializeメソッドを使用します。


2
通常、あなたは正しいでしょうが、常に呼び出されるとは限らないため、ActiveRecordモデルで初期化をオーバーライドするべきではありません。after_initialize代わりにメソッドを使用してください。
ルークレッドパス

デフォルトを設定するためだけにdefault_scopeを使用することは、間違いです。after_initializeが正解です。
joaomilho

4

やあ、みんな私は次のことをやった:

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

魅力的な作品!


3

これは長い間回答されてきましたが、私はデフォルト値を頻繁に必要とし、それらをデータベースに入れないことを好みます。私はDefaultValues懸念を作成します:

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

そして、それを私のモデルで次のように使用します:

class Widget < ApplicationRecord
  include DefaultValues

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

3

私は人々がそれを彼らの移行に入れることも見ましたが、むしろモデルコードで定義されるのを見たいです。

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

Rails 5の前の標準的なRailsの方法は、実際にはそれを移行に設定し、単に db/schema.rb設定することでした。あらゆるモデルのDBによって設定されているデフォルト値を確認したいときはいつでもforをてください。

@Jeff Perrinの回答(少し古い)とは対照的に、移行アプローチでは、使用時にデフォルトも適用されます Model.new、Railsのマジックにより。Rails 4.1.16での動作を確認。

多くの場合、最も単純なものが最善です。コードベースでの知識の負債と混乱の潜在的なポイントの削減。そして、それは「うまくいく」だけです。

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

または、新しい列を作成せずに列を変更する場合は、次のいずれかを実行します。

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

またはおそらくさらに良い:

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

列の変更方法のオプションについては、公式のRoRガイドを確認してください。

null: false追加の利点として、それはまた、そう以前にnullが同様にこのフィールドのデフォルト値が設定されたすべての既存のDBレコードことを禁止しDBにNULL値とを更新します。必要に応じて、このパラメーターを移行から除外することもできますが、非常に便利です。

Rails 5以降の標準的な方法は、@ Lucas Catonが言ったとおりです。

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

1

after_initializeソリューションの問題は、この属性にアクセスするかどうかに関係なく、DBからルックアップするすべての単一オブジェクトにafter_initializeを追加する必要があることです。遅延読み込みのアプローチをお勧めします。

属性メソッド(ゲッター)はもちろんメソッド自体なので、それらをオーバーライドしてデフォルトを提供できます。何かのようなもの:

Class Foo < ActiveRecord::Base
  # has a DB column/field atttribute called 'status'
  def status
    (val = read_attribute(:status)).nil? ? 'ACTIVE' : val
  end
end

誰かが指摘したように、Foo.find_by_status( 'ACTIVE')を実行する必要がある場合を除きます。その場合、DBがサポートしている場合は、データベースの制約に本当にデフォルトを設定する必要があると思います。


このソリューションと提案された代替案は、私の場合は機能しません。1つのクラスだけがその属性を持つSTIクラス階層と、DBクエリ条件で使用される対応する列があります。
cmoran92

1

複雑な検索を実行するとafter_initializeActiveModel::MissingAttributeErrorエラーが発生して問題が発生しました。

例えば:

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

「検索」.whereは条件のハッシュです

だから私はこのように初期化をオーバーライドすることでそれをやった:

def initialize
  super
  default_values
end

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

このsuper呼び出しはActiveRecord::Base、コードをカスタマイズする前にオブジェクトが正しく初期化されていることを確認するために必要です。つまり、default_values


私はそれが好きです。def initialize(*); super; default_values; endRails 5.2.0で行う必要がありました。さらに、.attributesハッシュでもデフォルト値を使用できます。
2018年

1
class Item < ActiveRecord::Base
  def status
    self[:status] or ACTIVE
  end

  before_save{ self.status ||= ACTIVE }
end

2
うーん...最初は独創的なようですが、少し考えてみると、いくつか問題があります。まず、すべてのデフォルト値は1点ではなく、クラス全体に散在しています(それらを検索または変更することを想像してください)。次に、最悪の場合、後でnull値(またはfalse値)を設定することはできません。
パラドハ2008年

デフォルトとしてnull値を設定する必要があるのはなぜですか?ARを使用すれば、何もせずにそのまま使用できます。ブール列を使用する場合のfalseについては、そうです、これは最善の方法ではありません。
マイクブリーン

ゲッター/セッターをクラスファイルに分散させないため、問題がなかった他のコーディング習慣について話すことはできません。また、最新のテキストエディターでは、メソッド(テキストメイトではshift-cmd-t)に簡単に移動できます。
マイクブリーン

@paradoja-私はそれを取り戻します、私は今それがnullを使うことでどこで故障するかを見ます。デフォルトとしてnullを使用する必要はありませんが、ある時点で実際に値をnullに変更したい場合。@paradoja、良いキャッチ、ありがとう。
マイクブリーン

動的に生成された属性でうまく機能するため、この方法を使用します。
デールキャンベル、


0

after_initializeメソッドは廃止されました。代わりにコールバックを使用してください。

after_initialize :defaults

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

ただし、マイグレーションで:defaultを使用するのが、まだ最もクリーンな方法です。


4
Rails 3では、after_initializeメソッド非推奨ではありません。実際、ISの例として提供するマクロ形式のコールバック非推奨です。詳細:guides.rubyonrails.org/...
Zabba

0

検証メソッドを使用すると、デフォルトの設定を多く制御できることがわかりました。更新のデフォルト(または検証の失敗)を設定することもできます。必要に応じて、挿入と更新に異なるデフォルト値を設定することもできます。デフォルトは#valid?まで設定されないことに注意してください。と呼ばれます。

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

検索::after_initializeもによって返された各オブジェクトによって呼び出されるためafter_initializeメソッドを定義に関しては、パフォーマンスの問題があるかもしれません http://guides.rubyonrails.org/active_record_validations_callbacks.html#after_initialize-and-after_find


保存の前にのみ検証が行われませんか?保存する前にデフォルトを表示したい場合はどうなりますか?
ヌレッティン2013

@nurettinそれは良い点であり、なぜあなたがそれをときどき欲しがるのかを私は見ることができますが、OPはこれを要件として言及しませんでした。保存されていない場合でも、すべてのインスタンスにデフォルトを設定するオーバーヘッドが必要かどうかを自分で決定する必要があります。代替策は、newアクションを再利用するためにダミーオブジェクトを保持することです。
ケルビン

0

列が「ステータス」タイプの列であり、モデルがステートマシンの使用に適している場合は、単純に実行できるaasm gemの使用を検討してください。

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

それでもまだ保存されていないレコードの値は初期化されませんが、自分でロールするなどの方法よりも少しクリーンでinitあり、すべてのステータスのスコープなどのaasmの他の利点を享受できます。



0

「default_value_for」gemを使用することを強くお勧めしますhttps : //github.com/FooBarWidget/default_value_for

初期化メソッドをオーバーライドする必要のあるトリッキーなシナリオがいくつかあります。

例:

dbのデフォルトはNULL、model / ruby​​で定義されたデフォルトは「何らかの文字列」ですが、何らかの理由で実際に値をnilに設定したい場合:MyModel.new(my_attr: nil)

ここでのほとんどのソリューションは、値をnilに設定できず、代わりにデフォルトに設定します。

OK、それで、||=アプローチをとる代わりに、あなたはmy_attr_changed?...に切り替えます

しかし今、あなたのDBのデフォルトは「いくつかの文字列」、モデル/ルビー定義のデフォルトは、「いくつかの他の文字列」であるが、特定のシナリオの下で、あなたが想像したい:「いくつかの文字列」(DBのデフォルト)に値を設定しますMyModel.new(my_attr: 'some_string')

これは、になりますmy_attr_changed?されて再び、ないあなたが希望するもの-値が順番にあなたのルビーに定義されたデフォルト・コードを発射し、「他のいくつかの文字列」に値を設定し、DBのデフォルトを、一致するため。


これらの理由から、これはafter_initializeフックだけでは適切に実行できないと思います。

繰り返しますが、「default_value_for」gemは正しいアプローチを取っていると思います:https : //github.com/FooBarWidget/default_value_for


0

これが私が使用したソリューションで、少し驚いてまだ追加されていません。

これには2つの部分があります。最初の部分は実際の移行でデフォルトを設定することであり、2番目の部分はモデルに検証が追加され、存在が正しいことを確認します。

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

したがって、デフォルトがすでに設定されていることがわかります。検証では、文字列に常に値があることを確認したいので、

 validates :new_team_signature, presence: true

これにより、デフォルト値が設定されます。(私にとっては「チームへようこそ」)、それからさらに一歩進んで、そのオブジェクトに常に値が存在することを確認します。

お役に立てば幸いです。


0
# 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

-2

Rails 3でdefault_scopeを使用する

api doc

ActiveRecordは、データベース(スキーマ)で定義されたデフォルトとアプリケーション(モデル)で行われたデフォルトの違いを覆い隠します。初期化中に、データベーススキーマを解析し、そこで指定されているデフォルト値を記録します。後でオブジェクトを作成するときに、データベースに触れることなく、スキーマで指定されたデフォルト値を割り当てます。

討論


meta_whereを使用する場合、バグが原因で、default_scopeが新しいARオブジェクトにデフォルトを割り当てることができない場合があります。
ViktorTrón2011年

このmeta_whereの問題は現在、[修正されましたmetautonomous.lighthouseapp.com/projects/53011/tickets/...
ヴィクトルTRON

3
使用しないでくださいdefault_scope。これにより、すべてのクエリで、設定したフィールドにこの条件が追加されます。それはあなたが望むものはほとんど決してありません。
ブラッド、2014年

@brad、面白い、あなたが言った、私は完全に同意する、それは悪だ:)。stackoverflow.com/questions/10680845/…で私のコメントを参照してください。
ViktorTrón2012年

-3

api docsからhttp://api.rubyonrails.org/classes/ActiveRecord/Callbacks.htmlbefore_validationモデルでメソッドを 使用すると、この例のように、作成と更新の呼び出しの特定の初期化を作成するオプションが提供されます(ここでもコードがapi docsの例から)番号フィールドはクレジットカード用に初期化されます。これを簡単に調整して、必要な値を設定できます

class CreditCard < ActiveRecord::Base
  # Strip everything but digits, so the user can specify "555 234 34" or
  # "5552-3434" or both will mean "55523434"
  before_validation(:on => :create) do
    self.number = number.gsub(%r[^0-9]/, "") if attribute_present?("number")
  end
end

class Subscription < ActiveRecord::Base
  before_create :record_signup

  private
    def record_signup
      self.signed_up_on = Date.today
    end
end

class Firm < ActiveRecord::Base
  # Destroys the associated clients and people when the firm is destroyed
  before_destroy { |record| Person.destroy_all "firm_id = #{record.id}"   }
  before_destroy { |record| Client.destroy_all "client_of = #{record.id}" }
end

彼がここで提案されていないことに驚いた


before_validationは、オブジェクトが永続化される準備ができるまでデフォルトを設定しません。プロセスが永続化する前にデフォルトを読み取る必要がある場合、値は準備されていません。
mmell 2012

いずれにしても、検証チェック中にデフォルト値を設定することはありません。ハックすらありません。初期化中に行う
Sachin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.