Reputation: 2661
I'm working on a Ruby on Rails podcast catcher and I can't figure out how to model per user episode state.
I'd like to have a model that includes information about an episode, and whether the user has played the episode or what they have rated it.
The table would look like this:
episodes_1
id | user_id | podcast_id | title | audio_url | duration| is_played | rating
If many users were subscribed to the same podcasts there would be many records with the same title and audio_url, so I thought of another table representation:
episodes_2
id | podcast_id | title | audio_url | duration
user_episode_data
id | user_id | episode_id | is_played | rating
If you joined user_episode_data
with episodes_2
on user_episode_data.episode_id = episode_2.id
you would get a table with all of the information in episodes_1
The second choice seems like a better way to store the data, but the first seems like a better way to present the data.
Is is possible to use multiple tables to store a model?
class Podcast < AcitiveRecord::Base
has_many :episodes
end
class Episode < ActiveRecord::Base
belongs_to :podcast
has_many :user_episode_datas
end
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :podcast
end
class User < ActiveRecord::Base
has_may :subscriptions
has_may :podcasts, through: :subscriptions
has_may :episodes, through :podcasts
has_many :user_episode_datas
end
class UserEpisodeData < ActiveRecord::Base
belongs_to :user
belongs_to :episode
end
I'd like user.episodes
to return the collection of all episodes for each podcast they are subscribed to, and I'd like user.episodes.first.is_played
to return true if that user has played that episode, but the episode model doesn't belong to any user, so I don't know how to model a one to one relationship between episode and user_episode_data in rails
Upvotes: 0
Views: 214
Reputation: 26193
There's no need to set up these relationships in the manner proposed. Instead, model Episode
and User
as a has_many :through
relationship:
class User < ActiveRecord::Base
has_many :views
has_many :episodes, through: :views
end
class View < ActiveRecord::Base
belongs_to :user
belongs_to :episode
end
class Episode < ActiveRecord::Base
has_many :views
has_many :users, through: :views
end
The canonical Rails guide provides an explanation of an example that very closely mirrors the scenario you've depicted. Here's what it has to say about has_many :through
relationships:
A has_many :through association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model.
Note that, in the example above, the View
model effectively acts as the join table. If you want to add attributes to the relationship between an Episode
and a User
– has_played
or rating
, for instance – you would add those attributes to the View
model.
Upvotes: 2