Ruby on Rails 5: двойная ассоциация между двумя моделями

Я работаю над этой проблемой уже несколько дней, и другие сообщения о переполнении стека, которые я просмотрел, либо очень старые, либо не совсем то, что мне нужно.

Проблема:

Участвуют три модели:

Поездка – представляет собой поездку и связанную с ней информацию. ПРИМЕЧАНИЕ. Не содержит никакой информации о членах экипажа.

Веха — представляет собой действие, предпринятое в поездке (для целей этой задачи, когда член экипажа садится или высаживается).

Член экипажа — представляет одного члена экипажа в поездке, у каждого члена экипажа есть контрольная точка посадки и высадки, которую можно разделить с другими членами экипажа, если они отправляются или высаживаются в одном и том же месте. Участники экипажа связаны с вехами как по embark_milestone_id, так и по disembark_milestone_id.

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

Сегмент страницы, который редактирует CrewMembers, обернут в конструктор fields_for. Модель Trips настроена на прием вложенных атрибутов модели CrewMember. Количество членов экипажа является переменным, и информация о каждом из них должна редактироваться отдельно (поэтому я не могу использовать select_tags, насколько мне известно). Это прекрасно работает для отображения членов экипажа в представлении, но не работает, когда я на самом деле пытаюсь обновить, потому что CrewMembers связаны с вехами как через embark_milestone_id, так и через disembark_milestone_id, а не простоmilestone_id.

Вопрос:

Имея все это в виду, есть ли способ «научить» рельсы распознавать CrewMembers через Milestones из формы поездки либо по embark_milestone_id, либо по disembark_milestone_id, либо по обоим?

У меня сложилось впечатление, что это не способ «Rails» сделать что-то подобное, но я хотел опубликовать эту идею в сообществе, прежде чем переходить к более сложному обходному пути.

Любые советы высоко ценится. Спасибо за уделенное время.

Код модели по запросу:

class CrewMember < ApplicationRecord
  belongs_to :guide
  belongs_to :milestone
end

class Trip < ApplicationRecord
  belongs_to :launch_slot, required: true
  has_many :milestones
  has_many :places, through: :milestones
  has_many :crew_members, through: :milestones, foreign_key: embark_milestone_id

  accepts_nested_attributes_for :milestones
  accepts_nested_attributes_for :crew_members
end

class Milestone < ApplicationRecord
  belongs_to :trip
  belongs_to :place

  has_many :crew_members
end

person TheSeesaw    schedule 13.06.2017    source источник
comment
Можете ли вы показать нам код модели?   -  person niceman    schedule 14.06.2017
comment
«Отлично работает, чтобы отображать членов экипажа в представлении, но не работает, когда я на самом деле пытаюсь обновить» - Не могли бы вы показать нам свое представление и как вы обновляетесь в данный момент?   -  person ihtishaam ahmed    schedule 14.06.2017


Ответы (1)


Похоже, вам нужны два отношения belongs_to от CrewMember до Milestone. Вам нужно будет дать этим отношениям разные имена, а затем переопределить имя класса по умолчанию, используя параметр class_name (см. документы):

class CrewMember < ApplicationRecord

  belongs_to :guide
  belongs_to :embark_milestone, class_name: :Milestone
  belongs_to :disembark_milestone, class_name: :Milestone

end

Затем из класса Milestone вам нужно определить два отношения has_many обратно в класс CrewMember. На этот раз вам также нужно будет указать external_key, так как это тоже нельзя вывести:

class Milestone < ApplicationRecord

  belongs_to :trip

  has_many :embarking_crew_members, class_name: :CrewMember,
    foreign_key: :embark_milestone_id
  has_many :disembarking_crew_members, class_name: :CrewMember, 
    foreign_key: :disembark_milestone_id

end

Ваш следующий вопрос заключается в том, как получить коллекцию allCrewMembers из модели Trip. Вы предложили вернуть либо членов экипажа, подключенных через embark_milestone_id, либо disembark_milestone_id. Прямого способа сделать это не существует — вам придется написать собственный метод, который соединяет отношения embarking_crew_members и disembarking_crew_members, а затем удаляет все дубликаты. Однако возможно ли, чтобы член экипажа высаживался, но не садился? ;-)

person Frankie Roberto    schedule 14.06.2017