Rails - 同时创建儿童和儿童的孩子

时间:2016-03-09 22:28:33

标签: ruby-on-rails ruby

我有user has_many user_itemsuser_items has_many user_item_images的关联。已经退出user。我可以创建一个新的user_item

user_item = user.user_items.create(name: 'foo')

我可以创建一个新的user_item_image

user_item.user_item_images.create(picture: file)

但我对user_item进行了验证,其中user_item不能存在user_item_image

如何同时创建这两个?

2 个答案:

答案 0 :(得分:3)

首先build两个项目然后保存父项。这将有效,因为:

  1. 只有在数据库中保存对象时才会调用验证
  2. 保存未保存的父级会自动保存所有关联的对象(通过has_one和has_many,belongs_to对象不会在没有自动保存选项的情况下保存)
  3. 验证(很可能)基于关联,关联包括目标中未保存但已分配的对象。但请注意,您无法在验证中使用count,因为它会执行COUNT查询,并且不会包含未保存的对象。请改为使用size,或者确定(对于未加载的关联,size调用计数为.to_a.size
  4. 您的代码应该像:

    user_item = user.user_items.build(name: 'foo')
    user_item.user_item_images.build(picture: file)
    user_item.save! # Bang for safety. If in controller, you can fork with if instead
    

答案 1 :(得分:1)

BroiSatse有一个正确的答案。如果你真的想在一行中做到这一点,你可以:

user_item = user.user_items.create!(name: 'foo', user_item_images_attributes: { picture: file })

在我自己的代码中,我通常只是为了可读性和可维护性而使它看起来像BroiSatse的代码 - 构建初始对象,添加相关项,然后保存。使用单行可能会快一点,但除非你做了数百万次,否则不太可能有所作为。