has_many: через существующий объект

очень похоже на этот вопрос, но не совсем то же самое.

У меня есть модели музыкантов и инструментов:

# musician.rb
class Musician < ActiveRecord::Base
  attr_accessible :instrument_attributes
  has_many :instrument_choices
  has_many :instruments, through: instrument_choices
  accepts_nested_attributes_for :instruments # with some other stuff
end

# instrument.rb
class Instrument < ActiveRecord::Base
  has_many :inverse_instrument_choices, class_name: "InstrumentChoice"
  has_many :musicians, through: :inverse_instrument_choices
  validates_uniqueness_of :name

# instrument_choice.rb
class InstrumentChoice < ActiveRecord::Base
  belongs_to :musician
  belongs_to :instrument
  validates_uniqueness_of :musician_id, scope: :instrument_id

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

Спасибо!


person Eric    schedule 12.11.2012    source источник


Ответы (1)


Вы можете создать InstrumentChoice либо через ассоциацию, либо путем непосредственного создания записи:

musician.instrument_choices.create(instrument: an_instrument)
# or
InstrumentChoice.create(musician: a_musician, instrument: an_instrument)

Поскольку вы на самом деле не храните никакой дополнительной информации в InstrumentChoice, вы можете использовать простую таблицу соединений, которая не требует собственной модели:

class Musician < ActiveRecord::Base
  has_and_belongs_to_many :instruments
end

class Instrument < ActiveRecord::Base
  has_and_belongs_to_many :musicians
end

musician.instruments << an_instrument

Чтобы обеспечить уникальность, вы можете добавить уникальное ограничение в таблицу соединений.

person fphilipe    schedule 12.11.2012
comment
Спасибо за быстрый ответ, Филипп. Проблема в том, что я делаю @musician = Musician.new(params['musicians']) в своем create действии, поэтому я думаю, что оно пытается автоматически создать ассоциации для меня, а это не то, чего я хочу, поскольку это попытается создать новые записи инструментов. Должен ли я просто загружать параметры по частям, а затем строить ассоциации, как вы говорите? - person Eric; 12.11.2012
comment
Значит, музыканта не существует, когда вы хотите хранить инструмент? Кроме того, поскольку я вижу params['musicians'], вы пытаетесь создать несколько музыкантов одновременно? - person fphilipe; 12.11.2012
comment
извините, имел ввиду музыканта. и мне нужно рассмотреть оба случая: как создание профиля музыканта и добавление его инструментов, так и редактирование профиля музыканта, где я могу (или не могу) добавлять/удалять ассоциации инструментов. - person Eric; 12.11.2012