Tyler Rowsell
Tyler Rowsell

Reputation: 125

Multiple has many to the same Model

I have a model Event with a nested model Attendee. Each attendee can be 1 of 3 roles (:guide, :marshal and :organizer).

class Event < ApplicationRecord

  has_many :attendees, dependent: :destroy
  has_many :guides, -> { Attendee.guide }
  has_many :marshals, -> { Attendee.marshal }
  has_many :organizers, -> { Attendee.organizer }
end

_

class Attendee < ApplicationRecord

  belongs_to :event

  validates :name, presence: true
  validates :role, presence: true
  validates :email, email: true

  enum role: %i[guide marshal organizer]

  scope :guide, -> { where(role: :guide) }
  scope :marshal, -> { where(role: :marshal) }
  scope :organizer, -> { where(role: :organizer) }
end

I would like my event registration form to have nested forms for each of the role types. I am trying something like this.

<%= form_for @event, url: event_create_path(@event.handle) do |f| %>

    <%= f.fields_for :organizers do |f| %>
        <%= render partial: "attendee_fields", locals: {f: f} %>
    <% end %>

    <%= f.fields_for :guides do |f| %>
        <%= render partial: "attendee_fields", locals: {f: f} %>
    <% end %>

    <%= f.fields_for :marshals do |f| %>
        <%= render partial: "attendee_fields", locals: {f: f} %>
    <% end %>
<% end %>

When a submit I receive the following error.

uninitialized constant Event::Guide

Any ideas on how to get around this?

Upvotes: 0

Views: 81

Answers (2)

max
max

Reputation: 102230

I would still go a completely different path to create a better domain model:

class Attendee
  has_many :attendences
  has_many :events, through: :attendences
end

class Attendance
  enum role: %i[guide marshal organizer]
  belongs_to :attendee
  belongs_to :event
end

class Event
  has_many :attendences
  has_many :attendees, through: :attendences

  Attendance.roles.each do |key,int|
    has_many key, through: :attendences,
                  source: :attendee,
                  -> { where(Attendance.call(key)) }
  end
end

The way you have modeled it an attendee is locked to a single role. This instead creates the roles scoped to an event.

Upvotes: 0

matthewd
matthewd

Reputation: 4435

Your Event model needs to look more like this:

class Event < ApplicationRecord
  has_many :attendees, dependent: :destroy
  has_many :guides, -> { guide }, class_name: "Attendee"
  has_many :marshals, -> { marshal }, class_name: "Attendee"
  has_many :organizers, -> { organizer }, class_name: "Attendee"
end

The extra associations need to know which model they're linking with -- as the error shows, they're currently guessing that e.g. guides is associated with some model named Guide.

(You also shouldn't need those scopes in Attendee, I don't think... I believe enum defines identical ones for you automatically.)

Upvotes: 1

Related Questions