【发布时间】:2013-11-16 18:31:58
【问题描述】:
鉴于 Rails 4 中的以下模型:
class Customer < ActiveRecord::Base
has_many :orders
end
class Order < ActiveRecord::Base
belongs_to :customer
end
我可以用新订单创建一个新客户,并通过保存父级同时保存他们:
2.0.0-p247 :001 > customer = Customer.new
2.0.0-p247 :002 > order = customer.orders.build
2.0.0-p247 :003 > customer.save
2.0.0-p247 :004 > order.customer_id
=> 3
这很好用。但是,Rails 将允许我只保存订单:
2.0.0-p247 :005 > customer = Customer.new
2.0.0-p247 :006 > order = customer.orders.build
2.0.0-p247 :007 > order.save
2.0.0-p247 :008 > order.customer_id
=> nil
如果我从不调用customer.save,那么我最终会得到一个数据库行,其中orders.customer_id 是null。
答案似乎是在其父客户的订单模型中添加validates 行,但我一直无法找到正确的公式。
添加
validates :customer, presence: true没有帮助,因为在上面的示例中,订单确实有一个客户——但它是一个还没有 ID 的新客户;order.save调用成功并且在数据库中orders.customer_id是null。添加
validates :customer, associated: true也无济于事;order.save成功并且在数据库中orders.customer_id是null。添加
validates :customer_id, presence: true确实会使order.save失败——但它也会使带有新子订单的customer.save无法成功,因为Rails 在customer.save发生之前检查所有customer.orders的有效性。
我知道 TDD 原则是“测试你自己的代码,而不是其他人的”,我希望 Rails 能够完成它的工作。但似乎在没有关闭这个漏洞的情况下,我可能会不小心编写代码来保存孤儿订单并最终在我的数据库中得到无效数据。我不想在检查order.customer 存在时乱扔代码。
解决这个问题的正确方法是什么?
【问题讨论】:
标签: ruby-on-rails activerecord