everett1992
everett1992

Reputation: 2661

How to model per user state in a Ruby on Rails application

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

Answers (1)

zeantsoi
zeantsoi

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 Userhas_played or rating, for instance – you would add those attributes to the View model.

Upvotes: 2

Related Questions