LearningRoR
LearningRoR

Reputation: 27222

Can you make one model hold different types of subscriptions?

Is it ok to have only one model that can hold many different types of subscriptions?

For example, lets say you can subscribe to comments, users, forum threads and news articles inside of an application. They all have different types of columns though. This how it would look with the associations setup.

Users
 attr_accessible :name, :role
 has_many :subscriptions
 has_many :comments, :threads, :articles, :through => :subscriptions

Comments
 :content, :rating, :number
 has_many :subscriptions
 has_many :subscribers, :through => :subscriptions, :class_name => 'User'  

Threads
 :title, :type, :main_category
 has_many :subscriptions
 has_many :subscribers, :through => :subscriptions, :class_name => 'User'

Articles
 :news_title, :importance
 has_many :subscriptions
 has_many :subscribers, :through => :subscriptions, :class_name => 'User'


Subscription
 :content, :rating, :number, :name, :role, :title, :type, :main_category, 
 :news_title, :importance, :user_id, :comment_id, :thread_id, :article_id 

 belongs_to :user, :comment, :thread, :article

Basically with one subscription model a user can choose to subscribe to a comment, thread or article and even all three at once. Can it work this way? Where one model can hold all different types of subscriptions, especially when you want to compare attributes to do certain things like articles for certain users?

Upvotes: 0

Views: 157

Answers (2)

Anton Dieterle
Anton Dieterle

Reputation: 656

You could try to do this more universal with polymorphic associations: http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

For example,

Subscription
  :subscriber_id, :subscribable_id, :subscribable_type

  belongs_to :subscriber, :class_name => "User"
  belongs_to :subscribable, :polymorphic => true

User
  has_many :subscriptions

Comment
  has_many :subscriptions, :as => :subscribable

Article
  has_many :subscriptions, :as => :subscribable

and then create new subscription like this

user.subscriptions.create(:subscribable => article)

and use it like this (if you actually care about type)

user.subscriptions.where(:subscribable_type => "Article").each do |subscription|
   article = subscription.subscribable
   # do stuff with article
end

Upvotes: 2

Ben Miller
Ben Miller

Reputation: 1484

This would be a good place to use polymorphic relationships.

You would replace comment_id, thread_id, article_id with two columns (subscribable_id, subscribable_type), and you would need to define the relationship for subscribable on subscription as polymorphic.

See section 2.9 of the Guide: http://guides.rubyonrails.org/association_basics.html

Upvotes: 1

Related Questions