Hey so I know with ActiveRecord I can have associations like belongs_to, has_many and has_many through, but how would it work if I have a model that has two associations with the same second model?
For example, if I have three class models Foo, Bar, & Baz. If
class Foo
has_many :baz
has_many :bar
has_many :bar, through: :baz
end
Basically, I want my foo concept to be able to create a bar but also to have bars through baz. Can I use it the way I have it set up there (with the other associations set up to match) and if I can, am I able to call .bars on my foo object to get back ALL the bars from both associations?
Top comments (4)
Hi Sav, can I ask why? What are you trying to accomplish modeling this association? What's the case for Foo to have many Bar by itself (one to many) and many Bar through Baz (many to many) at the same time?
I'm asking because maybe there's a simpler way to model these relationships.
If not I think you can tell AR to map one of those relationships with another alias, using
class_name
: guides.rubyonrails.org/association...See this answer as well stackoverflow.com/a/3098487/4186181
I'm definitely down to use some other sort of association if you think there is a better way.
So my goal is to have a travel app where I have a User who can have many Trips and many Destinations through Trips. I also want them to be able to create their own Destinations. The idea of this is so that other Users could add these Destinations to their Trips and leave comments on them and only the User who created the Destination can edit that Destination. So maybe I could just do the has_many through association, but when a User creates a Destination, it also has a hidden field with something like a created_by_id that stores that User's id to be able to reference back to it? Open to any other ideas as well.
Bear with me :-)
If I'm not mistaken:
A first version could be:
This way you can ask, given user Alice
The problem with this one is that a destination belongs to a single trip, so if two people want to add "Bora Bora" to their trip, they can't, unless you duplicate the record.
To allow two trips to have Bora Bora you need to have a many-to-many relationship between them (a trip has multiple destinations, a destination can appear in multiple trips).
So our models would become:
This way, you can know the following:
In your database you will have a list of possible destinations and each user can add them to their trips.
Next, we need to let these users create their own destinations, instead of just using the pre-populated ones.
The only difference between a predefined destination and a user created is the notion of creator. Other than having a flag
predefined
orcustom
or something like that you need to attach the id of the creator to a destination.Something like:
The reason why I'm calling the foreign key
creator_id
and notuser_id
is for future proofing. Now you're mapping a relationship of creator/creation between a user and a destination, you might want to add another type of relationship between the two entities in the future, and add another key likemoderator_id
or whatever. They all point to theUser
table, they just point to separate concepts mapped to different foreign keys.I haven't tested it but it should work. You need to create the various foreign keys in the migration:
Destination.creator_id
A tip: add the creation timestamp to the join table, so you'll know for free when the user has added the destination to their trip.
I hope I didn't forget something, let me know in case :-)
ps. my favorite gem to model permission (you're going to need something like it to describe the various actions a user can do, on destinations and comments) is Pundit
Awesome! I think that is exactly what I’m looking for! I’ll try it out and let you know how it goes. And thanks for the tip on Pundit! Excited to see how that works :)