Reputation: 461
What I Have So Far:
class Organization < ActiveRecord::Base
belongs_to :user
has_many :events
has_many :vips
end
class Event < ActiveRecord::Base
belongs_to :organization
has_many :vips
end
class Vip < ActiveRecord::Base
belongs_to :organization
belongs_to :event
end
My form for New Events:
<%= form_for [@organization, @event] do |f| %>
<p>
<%= f.label :when %>
<%= f.date_select :when %>
</p>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :vip %>
<%= f.select :vip_id, options_for_select(@organization.vips.all.map {|v| [v.name, v.id]}) %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
What my Models look like in the Console:
<Organization id: 1, name: "Test Org", created_at: "2015-08-25 04:46:03", updated_at: "2015-08-25 04:46:03", user_id: 1>
<Event id: 1, when: "2015-08-25 00:00:00", organization_id: 1, created_at: "2015-08-25 04:47:43", updated_at: "2015-08-25 04:47:43", name: "John's Event", vip_id: 1>
<Vip id: 1, name: "Captain", created_at: "2015-08-25 04:46:23", updated_at: "2015-08-25 06:51:47", organization_id: 1>
Note: I ran "rails generate migration add_vip_id_to_events vip:references" I did this because I want my handful of vips per organization able to be attached to a large amount of events. I was hoping that each event would know which vips were attached to it based on the vip_id column.
What I'm trying to Accomplish:
In my app I have Organization, Event, and Vip models. On my 'organization#show' page, I want to have all events for a given organization such that there would be a single date (e.g. "Mon, Sep 1 2015," "Tue, Sep 2 2015," and "Wed, Sep 3 2015") as a table header, and then all events on that date would be listed as "Event name, given by, Event Vip, at Event location, at Event time."
In the organization, I also want there to be Vips, that have their own 'Vip#Show' page within the organization. And, when you're filling out the event form, you'd be able to select the vip/vips that will be associated with that event (along with many other events) from the existing organization vips.
The Problem:
If I go to console, and attempt to find a vip attached to an event, I'll do the following:
@organization = Organization.find(1)
@event = @organization.events.first
@event.vips.first
and it returns => nil
Ok, so now I run a rails migration that adds an event_id column to vips, and manually populate it in console, so that it's pointing to the organizations first event (event_id = 1), and when I run the same code, I get:
@organization = Organization.find(1)
@event = @organization.events.first
@event.vips.first
=> #<Vip id: 1, name: "John", created_at: "2015-08-25 04:46:23", updated_at: "2015-08-25 06:51:47", organization_id: 1, event_id: 1>
This is a problem because I can't have my vips associated with only one event. I need them able to be associated with dozens of events, so that I can access them through block code, such as
<% @events = @organization.events.all %>
<% @events.each do |event| %>
<%= event.name %>
<% event.vips.each do |vip| %>
<%= vip.name %>
<% end %>
<% end %>
Upvotes: 1
Views: 43
Reputation: 178
Sounds like you're trying to create a many-to-many relationship and not a one-to-many as you currently have. If you take a look at the rails guides they explain this in detail here. The basic idea is to have a third table to define all of the relations between events and vip's. This table generally has a column for event_id and a column for vip_id. Each row in the table is a single association, so you can list multiple associations for the same vip or event.
This will allow you to call event.vips
or even vip.events
.
There's actually two options to get a many-to-many relation, you could use has_and_belongs_to_many
, or has_many :through
. The differences are also outlined in the guides, but to summarize the general idea is that you can use the has_many :through
if you need to attach additional information or methods to the relation itself. In this case, it is treated as its own separate entity or model. If you have no ned for this and are only interested in relating the two models that you already have then a has_and_belongs_to_many
is simpler to use and just requires the table in the database.
has_and_belongs_to_many
class Event < ActiveRecord::Base
has_and_belongs_to_many :vips
end
class VIP < ActiveRecord::Base
has_and_belongs_to_many :events
end
has_many :through
class Event < ActiveRecord::Base
has_many :event_vip_list
has_many :vips, through: :event_vip_list
end
class Vip < ActiveRecord::Base
has_many :event_vip_list
has_many :events, through: :event_vip_list
end
class EventVipList < ActiveRecord::Base
belongs_to :event
belongs_to :vip
end
Upvotes: 0
Reputation: 18070
It sounds like you may want
class Organization < ActiveRecord::Base
has_many :vips
class Event
has_many :event_vips
has_many :vips, :through => :event_vips
class EventVip < ActiveRecord::Base
belongs_to :event
belongs_to :vip
class Vip < ActiveRecord::Base
belongs_to :organization
has_many :events_vips
has_many :events, :through => :event_vips
This will make the vips a child of a single organization, and have the ability to connect with multiple events.
Upvotes: 1