Reputation: 583
I am creating a rails app to learn has_many :through associations... I know I didn't follow rails conventions, but that's because I want to learn all the different options Active Record has to offer.
My problem is, I think I have the relationships created, but I have no idea how to build invites and query them to get attendees, and attended_events. Do I have to create an invite first? If so, how do I associate it with an event? Then, how do I make it so that many users can attend the event? These questions may be pretty obvious for some of you, but I'm having trouble wrapping my head around it. Would anyone be kind enough to give me a basic run down? Did I even set up my code correctly to get the results I want? Here is my set up so far:
class Invite < ActiveRecord::Base
belongs_to :attending_guest, :class_name => "User"
belongs_to :attending_event, :class_name => "Event"
end
class User < ActiveRecord::Base
has_many :created_events, :foreign_key => "creator_id", :class_name => "Event"
has_many :invites, :foreign_key => :attending_guest_id
has_many :attended_events, through: :invites, source: :attending_event
end
class Event < ActiveRecord::Base
belongs_to :creator, :class_name => "User"
has_many :invites, :foreign_key => :attending_event_id
has_many :attendees, :through => :invites, :source => :attending_guest
end
Basically, an event has a creator, I think I have done that part correctly. Next, I want to be able to get a list of users that are attending the event. Also, I want to be able to see what events a user is going to. But how do I even build an invite and have one event be associated with a bunch of users, how does rails handle this? If anyone can please explain how I can go about doing these things and just give me some clarifications/tips, I would greatly appreciate it. Thanks you!
Upvotes: 3
Views: 67
Reputation: 1183
Using belongs_to
, has_many
etc. puts at your disposal some very handy methods for associating objects between each other. For example belongs_to
comes with:
1. association
2. association=(associate)
3. build_association(attributes = {})
4. create_association(attributes = {})
5. create_association!(attributes = {})
So far your question is how to build invites and have them associated with events and users, here's my suggestion:
Since in model Invite
you define 2 associations by using belongs_to
, you can use method No.5
of the above list as follows:
invite = Invite.create!
invite.create_attending_guest!(<the necessary attributes and respective values for creating a new user>)
invite.create_attending_event!(<the necessary attributes and respective values for creating a new event>)
or the other way around:
guest = User.create!(<attrs>)
event = Event.create!(<attrs>)
invite = Invite.create!(attending_guest: guest, attending_event: event)
I want to be able to see what events a user is going to
You can access them just like this:
u = User.find(5)
events = u.attended_events
how do I have one event be associated with a bunch of users
In this case you can use the method <<
added by has_many
(see here for the others):
u1 = User.create!(<attrs>)
u2 = User.create!(<attrs>)
u3 = User.create!(<attrs>)
event = Event.create!(<attrs>)
event.attendees << u1
event.attendees << u2
event.attendees << u3
Upvotes: 1
Reputation: 611
Are you able to create an instance of each ActiveModel individually and save it? Make sure you got the foreign keys right.
Provided the relations etc. are correct, I believe the (pseudo-) code should look like this:
creator = User.where(...
event = Event.new
event.save! # You need to save before adding to association
user = User.where(...
user.invites.create!(creator_id: creator)
This should be more-or-less it unless I missed something. Do wrap it in a transaction though.
Update: You should be able to do it without transaction I think:
creator = User.where(...
event = Event.new
user = User.where(...
user.invites.build(creator_id: creator)
event.save!
This should work and is way better because lets you use validators in Event that check if the required associations are there.
Upvotes: 1