构建has_many:通过新对象

时间:2012-03-18 00:21:40

标签: ruby-on-rails ruby-on-rails-3 activerecord has-many-through

我可能总体上做错了,但也许有人能够哼唱并帮忙。

问题

我希望能够在未保存的Object上建立关系,这样就可以了:

v = Video.new
v.title = "New Video"
v.actors.build(:name => "Jonny Depp")
v.save!

要添加到这个,这些将通过自定义方法生成,我试图修改它来工作,执行以下操作:

v = Video.new
v.title = "Interesting cast..."
v.actors_list = "Jonny Depp, Clint Eastwood, Rick Moranis"
v.save

此方法在video.rb

中如下所示
def actors_list=value
  #Clear for existing videos
  self.actors.clear

  value.split(',').each do |actorname|
    if existing = Actor.find_by_name(actorname.strip)
      self.actors << existing
    else
      self.actors.build(:name => actorname.strip)
    end
  end
end

我的期望

v.actors.map(&:name)
=> ["Jonny Depp", "Clint Eastwood", "Rick Moranis"]
不幸的是,这些策略既没有创造演员,也没有创建协会。哦,是的,你可能会问我:

在video.rb中

has_many :actor_on_videos
has_many :actors, :through => :actor_on_videos

accepts_nested_attributes_for :actors

我也尝试过修改actors_list=方法:

def actors_list=value
  #Clear for existing videos
  self.actors.clear

  value.split(',').each do |actorname|
    if existing = Actor.find_by_name(actorname.strip)
      self.actors << existing
    else
      self.actors << Actor.create!(:name => actorname.strip)
    end
  end
end

它创建了Actor,但如果视频在保存时失败,我宁愿不创建Actor。

所以我接近这个错误?或者我错过了一些明显的东西?

2 个答案:

答案 0 :(得分:1)

试试这个:

class Video < ActiveRecord::Base

  has_many :actor_on_videos
  has_many :actors, :through => :actor_on_videos

  attr_accessor :actors_list
  after_save    :save_actors

  def actors_list=names
    (names.presence || "").split(",").uniq.map(&:strip).tap do |new_list|
      @actors_list = new_list if actors_list_changes?(new_list)
    end
  end

  def actors_list_changes?(new_list)
    new_record? or 
      (actors.count(:conditions => {:name => new_list}) != new_list.size)
  end

  # save the actors in after save.
  def save_actors
    return true if actors_list.blank?
    # create the required names
    self.actors = actors_list.map {|name| Actor.find_or_create_by_name(name)}
    true
  end
end

答案 1 :(得分:0)

您无法将子项分配给没有ID的对象。您需要将演员存储在新视频对象中,并在视频保存并具有ID后保存这些记录。