Rails 3:在单个保存语句中创建多个关联的模型记录

时间:2013-08-02 11:45:18

标签: ruby-on-rails-3

我有一个类似的协会:

class Contact
  has_many :addresses
  has_many :email_addresses
  has_many :phone_numbers
end

我想在一次save语句中保存所有记录(地址,电子邮件和电话)。为此,我写了下面的代码。

contact = Contact.new(contact_params)
contact.addresses.build(address_params1)
contact.addresses.build(address_params2)
contact.email_addresses.build(email_params1)
contact.email_addresses.build(email_params2)
contact.phone_numbers.build(phone_params1)
contact.phone_numbers.build(phone_params2)
contact.save

它确实保存了联系人,但没有保存其他记录。我在这里缺少什么?

注意:我没有使用任何表格来保存数据。我正在导入数据。

2 个答案:

答案 0 :(得分:0)

contact模型中添加validates_associated,然后检查

validates_associated :addresses, :email_addresses, :phone_numbers

答案 1 :(得分:0)

首先,在我看来,你不能那样做。

  • 如果您想保存地址,则每个地址都需要一个contact_id。
  • 并且,当您保存联系人时,rails将首先验证联系人和所有子对象。这意味着 在保存任何记录之前,contact.valid?必须为true。
  • 由于在保存到db之前联系人没有id,因此任何地址中的contact_id都是空的。 因此,只要您需要同时创建新联系人及其子对象,contact.valid?将始终为false
  • 总结一下,这是轨道的步骤:
    1. 验证联系本身,成功!(注意:保存注释)
    2. 验证每个contact.addresses的地址,未提供contact_id,失败!

其次,我对你的问题的建议

关于您的问题“它确实保存了联系人,但没有保存其他记录。”,您需要告诉rails您要保存子对象(如下图所示)。否则,rails将忽略其他对象。但是,即使你这样做了,你也会遇到我上面描述的问题。

#contact.rb
accepts_nested_attributes_for :addresses
...

我的建议:你可以使用交易。

  1. creat contact
  2. 构建所有子对象
  3. 再次保存联系
  4. 代码示例:

    #contacts_controller.rb
    Contact.transaction do
      contact = Contact.new(contact_params)
      contact.addresses.build(address_params)
      ...
      contact.save
    end