Rails 3.1 - 在HestedTat关系的nested_attribute上找到find_or_create?

时间:2012-09-26 12:17:30

标签: ruby-on-rails-3 activerecord ruby-on-rails-3.1

我有许多艺术家和艺术家可以在许多版本中出现的版本。可以通过嵌套属性在我的发布表单中创建艺术家。我遇到麻烦的是让find_or_create为艺术家工作。

我在我的模型中定义了以下代码,因为您可以在ArtistRelease模型中看到一个相当荒谬的get / set / delete例程来实现所需的结果。这确实有效,但我不喜欢它。我知道通过find_or_create有更好的方法。有人可以帮忙吗?我应该在哪里放置find_or_create才能使用?

class Release < ActiveRecord::Base
  has_many :artist_releases, :dependent => :destroy
  has_many :artists, :through => :artist_releases
  accepts_nested_attributes_for :artists, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => :true
  accepts_nested_attributes_for :artist_releases
end

class Artist < ActiveRecord::Base
  has_many :artist_releases
  has_many :releases, :through => :artist_releases
end

class ArtistRelease < ActiveRecord::Base
  belongs_to :artist
  belongs_to :release

  before_create :set_artist_id
  after_create :destroy_artist

  default_scope :order => 'artist_releases.position ASC'

  private    
  def set_artist_id
    a = Artist.where("name =?", artist.name).reorder("created_at").find(:first)
    a.role = artist.role
    a.position = artist.position
    a.save
    artist_id = a.id
    self.artist_id =  artist_id
  end

  def destroy_artist
    c = Artist.count(:all, :conditions => [ "name = ?", artist.name])
      if c > 1
        a = Artist.where("name =?", artist.name).reorder("created_at").find(:last)
        a.destroy
      end
    end
end

1 个答案:

答案 0 :(得分:2)

您似乎正在寻找应在其中一个模型中覆盖的autosave_associated_records_for_[model_name]方法。

这里解释:accepts_nested_attributes_for with find_or_create?。这个例子是一个简单的has_many关联。

我已经开发了has_many :through关联,如下面的代码所示。

在我的应用中,我有一个order_item --< seat >-- client连接。我正在使用新的order_item表单创建客户端。解决方案允许我创建一个新的客户端和一个座位关联,或者只有一个座位关联,当客户端表中已经有一个提供电子邮件的客户端时。它不会更新现有客户端的其他属性,但也可以轻松扩展它们。

class OrderItem < ActiveRecord::Base
  attr_accessible :productable_id, :seats_attributes

  has_many :seats, dependent: :destroy
  has_many :clients, autosave: true, through: :seats

  accepts_nested_attributes_for :seats, allow_destroy: true   
end

class Client
  attr_accessible :name, :phone_1
  has_many :seats
  has_many :order_items, through: :seats
end

class Seat < ActiveRecord::Base
  attr_accessible :client_id, :order_item_id, :client_attributes

  belongs_to :client, autosave: true
  belongs_to :order_item

  accepts_nested_attributes_for :client

  def autosave_associated_records_for_client
    if new_client = Client.find_by_email(client.email)
      self.client = new_client
    else
      # not quite sure why I need the part before the if, 
      # but somehow the seat is losing its client_id value
      self.client = client if self.client.save!
    end
  end
end

希望它有所帮助!