Skip to content

Instantly share code, notes, and snippets.

@oojikoo-gist
Last active August 29, 2015 14:19
Show Gist options
  • Save oojikoo-gist/681404127816712d1f47 to your computer and use it in GitHub Desktop.
Save oojikoo-gist/681404127816712d1f47 to your computer and use it in GitHub Desktop.
rails: polymorphic module
##########################################################
# polymorphic as module
##########################################################
# app/models/comment.rb
#
class Comment < ActiveRecord::Base
belongs_to :commenter, :polymorphic => true
end
module Commentable
has_many :comments, as: :commentable
end
class Timesheet < ActiveRecord::Base
include Commentable
end
class ExpenseReport < ActiveRecord::Base
include Commentable
end
module Commentable
def self.included(base)
base.class_eval do
has_many :comments, as: :commentable
end
end
end
# app/models/concerns/commentable.rb
module Commentable
extend ActiveSupport::Concern
included do
has_many :comments, as: :commentable
end
end
# controller
class CommentsController < ApplicationController
before_filter :find_commenter
def create
@comment = @commenter.comments.create(params[:comments])
respond_to do |format|
format.html {redirect_to :controller => @commenter.class.to_s.pluralize.downcase, :action => :show, :id => @commenter.id}
end
end
private
def find_commenter
klass = params[:commenter_type].capitalize.constantize
@commenter = klass.find(params[:commenter_id])
end
end
##########################################################
##########################################################
# Combining has_many :through and polymorphic association
##########################################################
# There can be special cases where you need has_many :through with polymorphic association. Although not difficult to understand/implement, one might get confused the first time. So lets say Professor wants to know what courses/labs were assigned to his phd students/TAs. This can be made possible by doing the following.
```
# /app/models/professor.rb
class Professor < ActiveRecord::Base
has_many :teaching_assistants
has_many :course_tas, through: :teaching_assistants, source: :ta_duty, source_type: 'Course'
has_many :lab_tas, through: :teaching_assistants, source: :ta_duty, source_type: 'Lab'
end
```
```
# /app/models/teaching_assistant.rb
class TeachingAssistant < ActiveRecord::Base
belongs_to :professors
belongs_to :ta_duty, polymorphic: true
end
```
# That’s it, we have combined has_many :through and polymorphic association. To test you can make queries like Professor.first.course_tas. Note that we have added association between Professor and TAs, so make sure you make corresponding changes.
# !!!!! When adding Bi-directional Associations in rails application, one uses inverse_of: option provided by Active Record. inverse_of: does not work with polymorphic associations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment