Jacy Wang

Ruby on Rails Developer/Digital Analyst

Polymorphic Associations

In our app postit, the vote function is applied to both Post model and Comment model. A post has many votes and a comment also has many votes. In this case, we will use polymorphic associations.

First we will add votes table, rails generate migration create_votes.

1
2
3
4
5
6
7
8
9
10
11
12
13
class CreateVotes < ActiveRecord::Migration
  def change
    create_table :votes do |t|
      t.boolean :vote
      t.integer :user_id
      # t.references :voteable, polymorphic: true
      t.string :voteable_type
      t.integer :voteable_id

      t.timestamps
    end
  end
end

In the command line, run rake db:migrate.

:voteable_type column will record the model class name and :voteable_id will record the object ID that’s voted on.

Then the following changes should be applied,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# vote.rb
class Vote < ActiveRecord::Base
  belongs_to :creator, foreign_key: "user_id", class_name: "User"
  belongs_to :voteable, polymorphic: true

  validates_uniqueness_of :creator, scope: :voteable
end

# post.rb
class Post < ActiveRecord::Base
  has_many :votes, as: :voteable
end

# comment.rb
class Comment < ActiveRecord::Base
  has_many :votes, as: :voteable
end

# user.rb
class User < ActiveRecord::Base
  has_many :votes
end

Now we can retrieve @post.votes and set the vote by vote.post = Post.first. Good to go!