代码之家  ›  专栏  ›  技术社区  ›  lurker

存在关联时Rails隐式验证错误

  •  0
  • lurker  · 技术社区  · 4 年前

    我正在运行Rails 6.0.2.1。

    我在客户、发票和提案之间有一个相当简单的模型。发票属于提案(但这是可选的——发票不必基于提案)。此外,发票属于客户。

    class Invoice < ActiveRecord::Base
      belongs_to :client
      belongs_to :proposal, foreign_key: "prop_id"
      ...
    
    class Proposal < ActiveRecord::Base
      belongs_to :client
      has_one :invoice, foreign_key: "prop_id", dependent: :destroy
      ...
    
    class Client < ActiveRecord::Base
      has_many :proposals, dependent: :destroy
      has_many :invoices, dependent: :destroy
      ...
    

    这些模型彼此之间没有验证。也就是说,我没有验证表明发票必须有提案或客户。但是,如果我检查发票中任何字段的有效性,Rails会给我验证错误:

    > inv = Invoice.new
    => #<Invoice id: nil, client_id: nil, prop_id: nil, tocb_id: nil, fromcb_id: nil,
    date_invoice: "2020-02-10", written_by: nil, terms: nil, date_due: nil,
    status: "Pending", shipping: nil, amount: 0.0, amt_due: 0.0, deposit: nil,
    tax_rate: nil, comments: nil>
    > inv.errors.count
    => 0
    > inv.valid? :amount
    => false
    > inv.errors.count
    => 2
    > inv.errors
    => #<ActiveModel::Errors:0x000056466dac7a38 @base=#<Invoice id: nil, client_id: nil,
    prop_id: nil, ... , @messages={:client=>["must exist"], :proposal=>["must exist"]},
    @details={:client=>[{:error=>:blank}], :proposal=>[{:error=>:blank}]}>
    

    为什么它会将缺少的客户和缺少的提案标记为存在错误?

    0 回复  |  直到 4 年前
        1
  •  2
  •   Gautam    4 年前

    之所以会出现这种错误,是因为在Rails 5及更高版本中,每当我们定义一个“属于”关联时,默认情况下都需要有关联的记录。

    因此,您需要将客户和提案链接到发票,只有这样才能创建发票对象。这意味着你需要这么做-

    client = Client.create
    proposal = Proposal.create
    inv = Invoice.new(client: client, proposal: proposal)
    

    你也可以提到 belongs_to 关系作为 optional ,则不会验证关联对象的存在

    class Invoice < ActiveRecord::Base
      belongs_to :client, optional: true
      belongs_to :proposal, foreign_key: "prop_id", optional: true
      ...
    

    具有 optional: true

    inv = Invoice.new
    

    不会给出任何错误