2012-09-26 51 views
0

我有許多藝術家和藝術家可以出現在許多版本的發佈。藝術家可以通過嵌套屬性在我的發佈表單中創建。我遇到麻煩的是讓find_or_create工作在藝術家身上。Rails 3.1 - 對於HABTM關係的nested_attribute的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 

回答

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 

希望它有幫助!