module ClarkKent module Reportable extend ActiveSupport::Concern module ClassMethods def chain_up(query, params) params.each do |key,val| arel_method_name = self.arel_method_for(key) if arel_method_name.present? and self.respond_to? arel_method_name and val.present? query = self.send(arel_method_name, query, key, val) end end query end def report(params,report,count = false) @selects = [] @includes = [] @joins = [] @extra_scopes = [] @extra_filters = [] @groups = [] if 'ClarkKent::ReportEmail' == report.class.name @report_email = report report = @report_email.report end if count == false report.select_clauses.each do |select_clause| @selects.push select_clause end end report.arel_includes.each do |arel_include| @includes.push arel_include end report.arel_joins.each do |arel_join| @joins.push arel_join end report.extra_scopes.each do |extra_scope| @extra_scopes.push extra_scope end report.extra_filters.each do |extra_filter| @extra_filters.push extra_filter end report.groups.each do |grouper| @groups.push grouper end query = self.all if @report_email and @report_email.is_a? ClarkKent::ReportEmail params = @report_email.report_filter_params.symbolize_keys!.merge(params) else params = report.report_filter_params.symbolize_keys!.merge(params) end params.each do |param_type,param_value| if param_value.present? arel_method_name = self.arel_method_for(param_type) if arel_method_name.present? query = self.send(arel_method_name, query, param_type, param_value) report_column_options = report.column_options_for(param_type) if(report_column_options.respond_to? :joins) && (@joins.exclude? report_column_options.joins) @joins.push report_column_options.joins end if(report_column_options.respond_to? :includes) && (@includes.exclude? report_column_options.includes) @includes.push report_column_options.includes end if (count == false) && (report_column_options.respond_to? :custom_select) && (@selects.exclude? report_column_options.custom_select) @selects.push report_column_options.custom_select end end end end if @selects.any? query = query.select("DISTINCT " + self.column_names.map{|cn| self.table_name + '.' + cn}.join(', ')) @selects.uniq.each do |selectable| query = query.select(selectable) end end @includes.uniq.each do |includeable| query = query.includes(includeable) end if @includes.any? @extra_scopes.uniq.each do |extra_scope| query = query.send(extra_scope) end if @extra_scopes.any? @extra_filters.uniq.each do |extra_filter| query = query.where(extra_filter) end if @extra_filters.any? @joins.uniq.each do |joinable| query = query.joins(joinable).uniq end if @joins.any? @groups.uniq.each do |grouper| query = query.group(grouper) end if @groups.any? if count == true return query.count else return query end end def arel_method_for(param_type) method_name = self::AREL_METHODS[param_type.to_s] method_name ||= "#{param_type}_arel" if self.respond_to? "#{param_type}_arel" method_name end def simple_equality_arel(query, field_name, match_value) query. where(field_name.to_sym => match_value) end def before_date_arel(query, field_name, match_value) query. where("#{self.table_name}.#{field_name.to_s.sub(/_until/,'')} <= :date_limit", date_limit: match_value) end def after_date_arel(query, field_name, match_value) query. where("#{self.table_name}.#{field_name.to_s.sub(/_from/,'')} >= :date_limit", date_limit: match_value) end def order_arel(query, field_name, match_value) if match_value.is_a? Map order_column = match_value.order_column order_direction = match_value.order_direction else order_column, order_direction = match_value.split('-') end column_info = self::REPORT_COLUMN_OPTIONS[order_column.to_sym] if column_info.respond_to? :order_sql order_sql = column_info.order_sql order_sql = "#{order_sql} #{order_direction}" query = query.order(order_sql) if column_info.respond_to? :includes order_includes = column_info.includes query = query.includes(order_includes).references(order_includes) end query else query end end end end end