Rails 3.1 - find_or_create по вложенному_атрибуту для отношений HABTM?

У меня есть релизы, в которых может быть много артистов, а артисты могут появиться во многих релизах. Художники могут быть созданы в моей форме выпуска с помощью вложенных атрибутов. У меня проблемы с тем, чтобы заставить find_or_create работать с художником.

У меня есть следующий код, определенный в моих моделях, и, как вы можете видеть, довольно нелепая процедура get/set/delete в модели ArtistRelease для достижения желаемого результата. Это работает, но мне это не нравится. Я знаю, что есть лучший способ через 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

person Raoot    schedule 26.09.2012    source источник


Ответы (1)


Кажется, вы ищете метод 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

Надеюсь, поможет!

person tomruss    schedule 25.11.2012