使用find_or_create_by创建包含嵌套对象的对象

时间:2012-10-20 02:47:26

标签: ruby-on-rails activerecord

我想象这样的查询。

Movie.find_or_create_by_title(title: 'foo').photos.find_or_create_by_name(name: 'bar')

给定的查询将创建Photo对象,但不会考虑其父Movie

 => #<Photo id: 3, movie_id: nil …

有什么方法可以把电影传给它吗?

更新:我尝试同时保存两者的原因&#34;是因为我有一个验证,要求电影至少有一张照片。请参阅:https://stackoverflow.com/a/12962317/471313

2 个答案:

答案 0 :(得分:4)

我正在使用find_or_create_by更新的Rails 3.2语法,因为它将在Rails 4.0中弃用。重要的是在电影模型中设置accepts_nested_attributes_for,如下所示:

class Movie < ActiveRecord::Base
  has_many :photos
  accepts_nested_attributes_for :photos
end

这允许您在模型<relation-name>_attributes中使用photo_attributes形式指定模型属性中的键。

@movie = Movie.where(:title => 'foo').first_or_create :director => 'Steven Speilberg',
                                                      :photos_attributes => [{
                                                        :caption => "Thrilling!"
                                                      }]
@movie.save

在此之后,您只需保存父模型,这将自动保存子模型,再次在您的案例照片中。有必要首先保存父项,因为子项需要知道要放入子记录的id。因此,在保存@movie后,它会将其ID放在照片记录的movie_id字段中。它不能在父母之前保存孩子,因为它不知道要使用什么ID。

如果您在3.2之前使用Rails版本,它将如下所示:

@movie = Movie.find_or_create_by_title "W00t!", :director => 'Steven Speilberg',
                                                :photos_attributes => [{
                                                  :caption => "Thrilling!"
                                                }]

答案 1 :(得分:0)

movie = Movie.where(title: 'foo').first
if movie.nil?
  movie = Movie.new(title: 'foo')
  movie.photos.build(name: 'bar')
  movie.save
else
  movie.photos.create(name: 'bar')
end