Rails中Users、Artists、Events三表关联关系设置求助
Hey there! Let's work through setting up these associations in Rails—this is a super common scenario, so we can map it out clearly based on your needs.
First, let's break down the core relationships we need to model:
- A user can follow multiple artists, and an artist can have multiple followers (that's a many-to-many relationship)
- A user can follow multiple events, and an event can have multiple followers (another many-to-many)
- An event can have multiple artists, and an artist can participate in multiple events (yep, another many-to-many here—even though you mentioned "artists belong to events," most real-world cases call for artists joining multiple events. If you really want artists tied to a single event, we can adjust that, but I'll start with the flexible multi-event setup.)
Option 1: Separate Join Tables (Simple & Explicit)
This approach uses distinct join tables for each follow relationship, which is great for clarity if you don't plan to add more "followable" types later.
Step 1: Generate Migrations
First, create the necessary join tables via Rails generators:
- For user-artist follow connections:
rails generate migration CreateUserArtistFollows user:references artist:references
- For user-event follow connections:
rails generate migration CreateUserEventFollows user:references event:references
- For event-artist participation connections:
rails generate migration CreateEventArtist event:references artist:references
Run rails db:migrate to apply these changes to your database.
Step 2: Set Up Model Associations
Update your model files with these associations to tie everything together:
app/models/user.rb
class User < ApplicationRecord # Follow artists has_many :user_artist_follows, dependent: :destroy has_many :followed_artists, through: :user_artist_follows, source: :artist # Follow events has_many :user_event_follows, dependent: :destroy has_many :followed_events, through: :user_event_follows, source: :event end
app/models/artist.rb
class Artist < ApplicationRecord # Followed by users has_many :user_artist_follows, dependent: :destroy has_many :followers, through: :user_artist_follows, source: :user # Participate in events has_many :event_artists, dependent: :destroy has_many :events, through: :event_artists end
app/models/event.rb
class Event < ApplicationRecord # Followed by users has_many :user_event_follows, dependent: :destroy has_many :followers, through: :user_event_follows, source: :user # Host multiple artists has_many :event_artists, dependent: :destroy has_many :artists, through: :event_artists end
Option 2: Polymorphic Follow Model (Clean & Scalable)
If you might want users to follow other things later (like venues, playlists, etc.), a polymorphic association is smarter—it uses one table for all follow types instead of multiple.
Step 1: Generate Polymorphic Migration
First, create the polymorphic follow table, plus the event-artist join table as before:
rails generate migration CreateFollow user:references followable:references{polymorphic} rails generate migration CreateEventArtist event:references artist:references
Run rails db:migrate to apply these.
Step 2: Set Up Polymorphic Associations
app/models/user.rb
class User < ApplicationRecord has_many :follows, dependent: :destroy has_many :followed_artists, through: :follows, source: :followable, source_type: 'Artist' has_many :followed_events, through: :follows, source: :followable, source_type: 'Event' end
app/models/follow.rb
class Follow < ApplicationRecord belongs_to :user belongs_to :followable, polymorphic: true end
app/models/artist.rb
class Artist < ApplicationRecord has_many :follows, as: :followable, dependent: :destroy has_many :followers, through: :follows, source: :user has_many :event_artists, dependent: :destroy has_many :events, through: :event_artists end
app/models/event.rb
class Event < ApplicationRecord has_many :follows, as: :followable, dependent: :destroy has_many :followers, through: :follows, source: :user has_many :event_artists, dependent: :destroy has_many :artists, through: :event_artists end
How to Use These Associations
Once everything is set up, you can interact with the relationships easily:
- Let a user follow an artist:
current_user.followed_artists << Artist.find(1) - Get all artists a user follows:
current_user.followed_artists - Get all followers of an event:
event.followers - Add an artist to an event:
event.artists << Artist.find(2) - See all events an artist is part of:
artist.events
A quick note: I added dependent: :destroy to all has_many associations so that when a user/artist/event is deleted, related follow records are cleaned up automatically—this prevents orphaned data cluttering your database!
内容的提问来源于stack exchange,提问作者Sam Roberts

