簡體   English   中英

Rails 3:對默認值和關聯模型中的validates_presence_of驗證錯誤

[英]Rails 3: validates_presence_of validation errors on default value and in associated model

我有一個基本的發票設置模型: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

所以有兩個問題:

  1. 如果我刪除validates :invoice_id, :presence => true我沒有得到Line items invoice can't be blank錯誤消息,但為什么? 我想在line_items上驗證invoice_id,所有line_items都應該有invoice_id。 如何驗證line_items上的invoice_id而不會出現錯誤?

  2. 如果我將其設置為默認值,為什么我得到Status can't be blank 我可以在invoices_controller上設置它,但我認為應該在模型中設置默認值,對吧? 如何驗證狀態的存在並且在模型中仍然具有默認值?

發生這兩個驗證錯誤都是因為保存之前 (以及在before_save回調之前)調用了驗證。

我假設您正在使用nested_form來創建發票,同時它是行項目。 如果是這種情況,您不希望在訂單項上validates :invoice_id, :presence => true - 發票和訂單項同時進入,且發票尚未保存,所以它沒有id。 如果您保留驗證,則需要先創建並保存空發票,然后再創建訂單項,以便invoice_id可用。 如果您只想確保在任何編輯后仍設置invoice_id,您可以通過validates :invoice_id, :presence => true, :on => :update強制執行此操作validates :invoice_id, :presence => true, :on => :update這將在創建訂單項時跳過驗證(並且invoice_id尚不可用)。

您遇到validates :status, :presence => true問題validates :status, :presence => true出於類似的原因 - 通過請求進入的值正在驗證,並且“status”值不存在。 before_save回調在驗證后運行。 您可以在before_validationafter_initialization回調中設置默認值,並且在運行驗證時值將存在。

有關更多信息,請查看Rails的Callbacks文檔。

我將從2開始:在保存之前僅執行保存 ,這意味着,在對象通過驗證並即將保存之后。 如果驗證失敗 - 將不會執行。

至於1:您能舉例說明您是如何創建發票的嗎?

問題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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM