require 'active_record' # ActsAsCommentable module Juixe module Acts #:nodoc: module Commentable #:nodoc: def self.included(base) base.extend ClassMethods end module HelperMethods private def define_role_based_inflection(role) send("define_role_based_inflection_#{Rails.version.first}", role) end def define_role_based_inflection_3(role) has_many "#{role.to_s}_comments".to_sym, has_many_options(role).merge(:conditions => { role: role.to_s }) end def define_role_based_inflection_4(role) has_many "#{role.to_s}_comments".to_sym, -> { where(role: role.to_s) }, has_many_options(role) end def has_many_options(role) {:class_name => "Comment", :as => :commentable, :dependent => :destroy, :before_add => Proc.new { |x, c| c.role = role.to_s } } end end module ClassMethods include HelperMethods def acts_as_commentable(*args) options = args.to_a.flatten.compact.partition{ |opt| opt.kind_of? Hash } comment_roles = options.last.blank? ? nil : options.last.flatten.compact.map(&:to_sym) join_options = options.first.blank? ? [{}] : options.first throw 'Only one set of options can be supplied for the join' if join_options.length > 1 join_options = join_options.first class_attribute :comment_types self.comment_types = (comment_roles.blank? ? [:comments] : comment_roles) if !comment_roles.blank? comment_roles.each do |role| define_role_based_inflection(role) end has_many :all_comments, { :as => :commentable, :dependent => :destroy, class_name: 'Comment' }.merge(join_options) else has_many :comments, {:as => :commentable, :dependent => :destroy}.merge(join_options) end comment_types.each do |role| method_name = (role == :comments ? "comments" : "#{role.to_s}_comments").to_s class_eval %{ def self.find_#{method_name}_for(obj) commentable = self.base_class.name Comment.find_comments_for_commentable(commentable, obj.id, "#{role.to_s}") end def self.find_#{method_name}_by_user(user) commentable = self.base_class.name Comment.where(["user_id = ? and commentable_type = ? and role = ?", user.id, commentable, "#{role.to_s}"]).order("created_at DESC") end def #{method_name}_ordered_by_submitted Comment.find_comments_for_commentable(self.class.name, id, "#{role.to_s}").order("created_at") end def add_#{method_name.singularize}(comment) comment.role = "#{role.to_s}" #{method_name} << comment end } end end end end end end ActiveRecord::Base.send(:include, Juixe::Acts::Commentable)