4

モデルを使用した基本的な請求書のセットアップがあります: Invoice、Item、LineItems。

# invoice.rb
class Invoice < ActiveRecord::Base
  has_many :line_items, :dependent => :destroy
  validates_presence_of :status

  before_save :default_values

  def default_values
    self.status = 'sent' unless self.status
  end
end

# item.rb
class Item < ActiveRecord::Base
  has_many :line_items
  validates_presence_of :name, :price
end

# line_item.rb
class LineItem < ActiveRecord::Base
  belongs_to :item
  belongs_to :invoice 
  before_save :default_values

  validates_presence_of :invoice_id
  validates :item_id, :presence => true
end

モデルには他にもありますが、簡単にするために上記のもののみを示しました。

次のエラーが表示されます。

2 errors prohibited this invoice from being saved:
  Line items invoice can't be blank
  Status can't be blank

だから2つの問題:

  1. 削除するvalidates :invoice_id, :presence => trueと、Line items invoice can't be blankエラー メッセージは表示されなくなりますが、なぜですか? line_items の送り状 ID を検証したいのですが、すべての line_items には送り状 ID があるはずです。エラーを発生させずに line_items の Invoice_id を検証するにはどうすればよいですか?

  2. Status can't be blankデフォルト値として設定するとエラーが発生するのはなぜですか? おそらくinvoices_controllerで設定できますが、デフォルト値はモデルに設定する必要があると思いますよね?ステータスの存在を検証し、モデルにデフォルト値を保持するにはどうすればよいですか?

4

3 に答える 3

4

これらの検証エラーは両方とも、保存前 (およびコールバックbefore_save) に検証が呼び出されるために発生しています。

Nested_form を使用して請求書と明細を同時に作成していると仮定しています。このような場合はvalidates :invoice_id, :presence => true、請求書と項目が同時に入ってきて、請求書がまだ保存されていないため、ID がありません。検証をそのままにしておく場合は、最初に空の請求書を作成して保存し、後で項目を作成して、invoice_id を使用できるようにする必要があります。編集後にinvoice_idが設定されていることのみを確認したい場合は、これを強制してvalidates :invoice_id, :presence => true, :on => :update、明細項目の作成時に検証をスキップできます(invoice_idはまだ利用できません)。

validates :status, :presence => true同様の理由で問題が発生しています-リクエストを介して受信した値が検証されており、「ステータス」値がありません。before_saveコールバックは検証後に実行されます。before_validationまたはコールバックでデフォルト値を設定するafter_initializationと、検証が実行されるときにその値が表示されます。

詳細については、Rails のCallbacksドキュメントを参照してください。

于 2012-06-26T17:44:25.730 に答える
1

2: before save は save の前にのみ実行されます。つまり、オブジェクトが検証に合格し、保存されようとしている後です。検証が失敗した場合 - 実行されません。

1 について: 請求書を作成しようとしている方法の例を挙げていただけますか?

于 2012-06-26T17:44:53.220 に答える
0

問題1

validates_associated関連付けられたモデルがすべて有効であることを確認する方法を試してください

問題 2

ほとんどの回答が言うようbefore_saveに、検証後に呼び出されます。あなたが探している魔法はafter_initialize、オブジェクトのinitializeメソッドが呼び出された後に実行されるものです。

class Invoice < ActiveRecord::Base
  after_initialize :default_values
  validates :status, presence: true

private

  def default_values
    self.status ||= 'sent'
  end
end
于 2012-06-26T18:30:26.760 に答える