Polymorphism: As per Wiki, it is the provision of a single interface to entities of different types.
Polymorphic Associations (in Rails’ terms): With polymorphic associations, a model can belong to more than one other model, on a single association.
For example (in this blog), we will have a
Comment model that belongs to either a
Post model or a
First, we generate our Comment model. Below command will generate model, migration and test.
rails g model Comment commentable_type:string commentable_id:integer user_id:integer body:text
Now we will define our models as shown below:
class Comment < ActiveRecord::Base belongs_to :commentable, polymorphic: true end class Post < ActiveRecord::Base has_many :comments, as: :commentable end class Forum < ActiveRecord::Base has_many :comments, as: :commentable end
Alright, that would be all for modeling. Lets go to Controllers:
comments_controller.rb for all models we want to use this polymorphic association. So for our example, we create
controllers > posts > comments_controller.rb
controllers > forums > comments_controller.rb
Sample code for posts > comments_controller.rb
class Posts::CommentsController < ApplicationController before_action :authenticate_user! before_action :set_post # Create comment for post def create @comment = @post.comments.new(comment_params) @comment.user = current_user @comment.save redirect_to @post, notice: "Comment added successfully" end private def set_post @post = Post.find(params[:post_id]) end def comment_params params.require(:comment).permit(:body) end end
Similarly you can add for all the models using this polymorphic association. (You may create one comments_controller and put all common code in there).
Lets add routes for the comments at
resources :posts do resources :comments, module: :posts end resources :forums do resource :comments, module: :forums end
Okay, most of our setup is ready. Lets add code to view all comments and form to add one.
<h3>Comments</h3> <% @post.comments.each do |comment| %> <div class="well right"> <%= comment.body %> </div> <% end %> <%= form_for [@post, Comment.new] do |f| %> <div class="form-group"> <%= f.text_area :body, class: "form-control" %> </div> <%= f.submit class: "btn btn-primary" %> <% end %>
Alright, thats it. We have setup our polymorphic association.
I hope you like this post. Please comment down below you have doubts/questions or request for any topics. Thanks for reading!