module ModelMixins::TableBuilderClassMethods

Attributes

can_edit_description[RW]

Public Instance Methods

check_non_existing_colum_order_by(settings, params) click to toggle source
# File lib/model_mixins/table_builder_class_methods.rb, line 722
def check_non_existing_colum_order_by(settings, params)
  order_by_params = params[:order_by].dup.gsub(/___unknown___\./, "") #some cleaning job
  order_by_params = order_by_params.gsub(/___sql_expression___\./, "") #some cleaning job

  order_by_arr = order_by_params.split(",")
  order_by_arr.each_with_index do |one_order_by, index|
    if one_order_by.match(/^.*?non_existing_column___.*$/i)
      identifier_and_direction = one_order_by.split("non_existing_column___").second
      identifier = identifier_and_direction.split(" ").first
      order_by_direction = identifier_and_direction.split(" ").second
      settings[:columns].each do |col|
        if !col[:select_as].blank? && !col[:format_method].blank? && col[:format_method] == identifier
          order_by_arr[index] = col[:order_by].gsub(",", " #{order_by_direction} ,") + " #{order_by_direction}"
        else
          ""
        end
      end
    else
      ""
    end
  end
  params[:real_order_by] = order_by_arr*","
end
editable_table_load_colors(settings, object, all_items_row_ids) click to toggle source
# File lib/model_mixins/table_builder_class_methods.rb, line 747
def editable_table_load_colors(settings, object, all_items_row_ids)
  if object.respond_to?(:klass)
    object_class = object.klass
  else
    object_class = object
  end

  # if model has cell colors

  if (object_class.new.respond_to?(:editable_table_cell_colors))
    cell_colors = EditableTableCellColor.where(:owner_type => object_class.to_s, :owner_id => all_items_row_ids).all
    cell_colors_for_settings = {}
    cell_colors.each do |c|
      cell_colors_for_settings[c.owner_id] ||= {}
      cell_colors_for_settings[c.owner_id][c.cell_name] ||= {}
      cell_colors_for_settings[c.owner_id][c.cell_name]["color"] = c.color
      cell_colors_for_settings[c.owner_id][c.cell_name]["background_color"] = c.background_color
    end
    unless cell_colors_for_settings.blank?
      settings.merge!({:cell_colors => cell_colors_for_settings})
    end
  end

  # if model has row colors
  if (object_class.new.respond_to?(:editable_table_row_colors))
    row_colors = EditableTableRowColor.where(:owner_type => object_class.to_s, :owner_id => all_items_row_ids)
    row_colors_for_settings = {}
    row_colors.each do |c|
      row_colors_for_settings[c.owner_id] ||= {}
      row_colors_for_settings[c.owner_id]["color"] = c.color
      row_colors_for_settings[c.owner_id]["background_color"] = c.background_color
    end
    unless row_colors_for_settings.blank?
      settings.merge!({:row_colors => row_colors_for_settings})
    end
  end
end
filter(object, settings, params, per_page = 10, total_count = nil) click to toggle source
# File lib/model_mixins/table_builder_class_methods.rb, line 429
def filter(object, settings, params, per_page = 10, total_count = nil)
  inactive_columns = get_columns_with_inactive_filter settings


  order_by = params[:real_order_by]

  cond_str = ""
  cond_hash = {}
  having_cond_str = ""
  having_cond_hash = {}

  case settings[:filter_method]
    when "only_by_checkboxes"
      # filtering only by checkboxes
      cond_str = "(#{settings[:row][:id]} IN (:checkboxes))"
      cond_hash = {:checkboxes => params["checkbox_pool"].split(",")}
      per_page = nil # no paginate for checkbox filter
    else
      params = process_number_exact_filter(params)


      # filtering by table filters
      if !params.blank? && params['find']
        params['find'].each_pair do |i, v|
          next if inactive_columns.include?(i)

          i = i.gsub(/___unknown___\./, "") #some cleaning job
          unless v.blank?
            if i.match(/^.*?non_existing_column___.*$/i)
              identifier = i.split("non_existing_column___").second
              settings[:columns].each do |col|
                if !col[:select_as].blank? && !col[:format_method].blank? && col[:format_method] == identifier
                  cond_str += " AND " unless cond_str.blank?
                  cond_str += "( "
                  sub_cond = ""
                  col[:select].split(",").each do |sub_cond_col|
                    sub_cond += " OR " unless sub_cond.blank?
                    non_existing_column_i = col[:select_as] + "." + sub_cond_col.gsub(" ", "")
                    cond_id = "find_#{non_existing_column_i.gsub(/\./, '_')}"
                    sub_cond += "#{non_existing_column_i} LIKE :#{cond_id}" #OR guest_email LIKE :find"
                    cond_hash.merge!({cond_id.to_sym => "%#{v}%"})
                  end
                  cond_str += sub_cond + " )"
                else
                  ""
                end
              end
            else
              if i.match(/^.*?___sql_expression___.*$/i)
                i = i.gsub(/___sql_expression___\./, "") #some cleaning job

                having_cond_str += " AND " unless having_cond_str.blank?
                cond_id = "find_#{i.gsub(/\./, '_')}"
                having_cond_str += "#{i} LIKE :#{cond_id}" #OR guest_email LIKE :find"
                having_cond_hash.merge!({cond_id.to_sym => "%#{v}%"})
              else
                cond_str += " AND " unless cond_str.blank?
                cond_id = "find_#{i.gsub(/\./, '_')}"
                cond_str += "#{i} LIKE :#{cond_id}" #OR guest_email LIKE :find"
                cond_hash.merge!({cond_id.to_sym => "%#{v}%"})
              end
            end
          end
        end
      end

      if !params.blank? && params['find_exact']
        params['find_exact'].each_pair do |i, v|
          next if inactive_columns.include?(i)

          i = i.gsub(/___unknown___\./, "") #some cleaning job
          unless v.blank?
            if i.match(/^.*?non_existing_column___.*$/i)
              puts "It has to be existing column for exact match"
            else
              if i.match(/^.*?___sql_expression___.*$/i)
                i = i.gsub(/___sql_expression___\./, "") #some cleaning job

                having_cond_str += " AND " unless having_cond_str.blank?
                cond_id = "find_#{i.gsub(/\./, '_')}"
                having_cond_str += "#{i} = :#{cond_id}" #OR guest_email LIKE :find"
                having_cond_hash.merge!({cond_id.to_sym => "#{v}"})
              else
                cond_str += " AND " unless cond_str.blank?
                cond_id = "find_#{i.gsub(/\./, '_')}"
                cond_str += "#{i} = :#{cond_id}" #OR guest_email LIKE :find"
                cond_hash.merge!({cond_id.to_sym => "#{v}"})
              end
            end
          end
        end
      end

      # ToDo ladas add having condition to others
      if !params.blank? && params['multichoice']
        params['multichoice'].each_pair do |i, v|
          next if inactive_columns.include?(i)

          i = i.gsub(/___unknown___\./, "") #some cleaning job
          unless v.blank?
            if i.match(/^.*?___sql_expression___.*$/i)
              i = i.gsub(/___sql_expression___\./, "") #some cleaning job
              having_cond_str += " AND " unless having_cond_str.blank?
              cond_id = "multichoice_#{i.gsub(/\./, '_')}"

              having_cond_str += "#{i} IN (:#{cond_id})" #OR guest_email LIKE :find"
              having_cond_hash.merge!({cond_id.to_sym => v})
            else
              cond_str += " AND " unless cond_str.blank?
              cond_id = "multichoice_#{i.gsub(/\./, '_')}"

              cond_str += "#{i} IN (:#{cond_id})" #OR guest_email LIKE :find"
              cond_hash.merge!({cond_id.to_sym => v})
            end
          end
        end
      end

      if !params.blank? && (params['date_from'])
        from_hash = params['date_from']

        from_hash.each_pair do |i, v|
          next if inactive_columns.include?(i)

          i = i.gsub(/___unknown___\./, "") #some cleaning job
          unless v.blank?
            if i.match(/^.*?___sql_expression___.*$/i)
              i = i.gsub(/___sql_expression___\./, "") #some cleaning job
              having_cond_str += " AND " unless having_cond_str.blank?
              cond_id = "date_from_#{i.gsub(/\./, '_')}"
              having_cond_str += "#{i} >= :#{cond_id}" #OR guest_email LIKE :find"
              having_cond_hash.merge!({cond_id.to_sym => "#{v}"})
            else
              v = Time.parse(v) rescue nil # queries to database has to be in utc date
              unless v.nil?
                cond_str += " AND " unless cond_str.blank?
                cond_id = "date_from_#{i.gsub(/\./, '_')}"
                cond_str += "#{i} >= :#{cond_id}" #OR guest_email LIKE :find"
                cond_hash.merge!({cond_id.to_sym => "#{v.utc}"})
              end
            end
          end
        end
      end

      if !params.blank? && (params['date_to'])
        to_hash = params['date_to']

        to_hash.each_pair do |i, v|
          next if inactive_columns.include?(i)

          i = i.gsub(/___unknown___\./, "") #some cleaning job
          unless v.blank?
            if i.match(/^.*?___sql_expression___.*$/i)
              i = i.gsub(/___sql_expression___\./, "") #some cleaning job
              having_cond_str += " AND " unless having_cond_str.blank?
              cond_id = "date_to_#{i.gsub(/\./, '_')}"
              having_cond_str += "#{i} <= :#{cond_id}" #OR guest_email LIKE :find"
              having_cond_hash.merge!({cond_id.to_sym => "#{v}"})
            else
              v = Time.parse(v) rescue nil # queries to database has to be in utc date
              unless v.nil?
                cond_str += " AND " unless cond_str.blank?
                cond_id = "date_to_#{i.gsub(/\./, '_')}"
                cond_str += "#{i} <= :#{cond_id}" #OR guest_email LIKE :find"
                cond_hash.merge!({cond_id.to_sym => "#{v.utc}"})
              end
            end
          end
        end
      end


      if !params.blank? && (params['number_from'])
        from_hash = params['number_from']

        from_hash.each_pair do |i, v|
          next if inactive_columns.include?(i)

          i = i.gsub(/___unknown___\./, "") #some cleaning job
          unless v.blank?
            if i.match(/^.*?___sql_expression___.*$/i)
              i = i.gsub(/___sql_expression___\./, "") #some cleaning job
              having_cond_str += " AND " unless having_cond_str.blank?
              cond_id = "date_from_#{i.gsub(/\./, '_')}"
              having_cond_str += "#{i} >= :#{cond_id}" #OR guest_email LIKE :find"
              having_cond_hash.merge!({cond_id.to_sym => "#{v}"})
            else
              cond_str += " AND " unless cond_str.blank?
              cond_id = "date_from_#{i.gsub(/\./, '_')}"
              cond_str += "#{i} >= :#{cond_id}" #OR guest_email LIKE :find"
              cond_hash.merge!({cond_id.to_sym => "#{v}"})
            end
          end
        end
      end

      if !params.blank? && (params['number_to'])
        to_hash = params['number_to']

        to_hash.each_pair do |i, v|
          next if inactive_columns.include?(i)

          i = i.gsub(/___unknown___\./, "") #some cleaning job
          unless v.blank?
            if i.match(/^.*?___sql_expression___.*$/i)
              i = i.gsub(/___sql_expression___\./, "") #some cleaning job
              having_cond_str += " AND " unless having_cond_str.blank?
              cond_id = "date_to_#{i.gsub(/\./, '_')}"
              having_cond_str += "#{i} <= :#{cond_id}" #OR guest_email LIKE :find"
              having_cond_hash.merge!({cond_id.to_sym => "#{v}"})
            else
              cond_str += " AND " unless cond_str.blank?
              cond_id = "date_to_#{i.gsub(/\./, '_')}"
              cond_str += "#{i} <= :#{cond_id}" #OR guest_email LIKE :find"
              cond_hash.merge!({cond_id.to_sym => "#{v}"})
            end
          end
        end
      end


    #items = self.joins("LEFT OUTER JOIN intranet_text_pages ON resource_id = intranet_text_pages.id").where(cond_str, cond_hash).paginate(:page => params[:page], :per_page => per_page).order(order_by).selection(settings)
    #if params[:page].to_i > items.total_pages && items.total_pages > 0
    #  params[:page] = 1
    #  items = self.where(cond_str, cond_hash).paginate(:page => params[:page], :per_page => per_page).order(order_by).selection(settings)
    #end
    #items
  end
  ret = where(cond_str, cond_hash).order(order_by)
  ret = ret.having(having_cond_str, having_cond_hash) unless having_cond_str.blank?

  # if there are additional joins i will add them
  settings[:columns].each do |col|
    col[:table_primary_key] = "id" if col[:table_primary_key].blank?
    if !col[:join_on].blank?
      join_on_select = col[:select] + ", #{col[:table_primary_key]}" # adding primary key so it can be used in on condition
      ret= ret.joins("LEFT OUTER JOIN (SELECT #{join_on_select} FROM #{col[:table]}) #{col[:select_as]} ON #{col[:select_as]}.#{col[:table_primary_key]}=#{col[:join_on]}")
    end
  end


  if per_page && per_page > 0
    # only when i need pagination
    if total_count.blank?
      # if I call this more times, I can pass the total count and not count it multiple times
      # fuck will paginate, if there are agregated queries that I use for condition, will_paginage will delete it
      # i am counting rows on my own (as sugested in will paginete gem, when the query got more complex)
      if (settings[:total_count_cache].blank?)
        # I am not caching total count. Be advised in table cca. 200 000 rows total count take about 1 second to compute, it very much.
        if object.respond_to?(:klass)
          mysql_count = object.klass.find_by_sql("SELECT COUNT(*) AS count_all FROM (" + ret.selection(settings).to_sql + ") count")
        else
          mysql_count = object.find_by_sql("SELECT COUNT(*) AS count_all FROM (" + ret.selection(settings).to_sql + ") count")
        end

        ret = ret.paginate(:page => params[:page], :per_page => per_page, :total_entries => mysql_count.first[:count_all])
      else
        # I am caching total count
        # todo find out how to cache this when everything can change, maybe I can cache only not filtered version
        # !!!!!!1 dont turn this on till then

        total_count = Rails.cache.fetch(settings[:form_id] + "__cached_total_count", :expires_in => settings[:total_count_cache]) do
          if object.respond_to?(:klass)
            mysql_count = object.klass.find_by_sql("SELECT COUNT(*) AS count_all FROM (" + ret.selection(settings).to_sql + ") count")
          else
            mysql_count = object.find_by_sql("SELECT COUNT(*) AS count_all FROM (" + ret.selection(settings).to_sql + ") count")
          end
          mysql_count.first[:count_all]
        end
        ret = ret.paginate(:page => params[:page], :per_page => per_page, :total_entries => total_count)
      end
    else
      ret = ret.paginate(:page => params[:page], :per_page => per_page, :total_entries => total_count)
    end
  end

  ret
end
get_columns_with_inactive_filter(settings) click to toggle source
# File lib/model_mixins/table_builder_class_methods.rb, line 709
def get_columns_with_inactive_filter settings
  inactive_cols = []
  settings[:columns].each do |col|
    col[:table] = "___unknown___" if col[:table].blank?
    col[:table] = "___sql_expression___" unless col[:sql_expression].blank?

    if col[:inactive_filter]
      inactive_cols << "#{col[:table]}.#{col[:name]}"
    end
  end
  inactive_cols
end
make_sumarizations!(object, summarized_paged_cols, paged_cols_arel, summarized_all_cols, all_cols_arel) click to toggle source
# File lib/model_mixins/table_builder_class_methods.rb, line 239
def make_sumarizations!(object, summarized_paged_cols, paged_cols_arel, summarized_all_cols, all_cols_arel)
  # make summarizations, will set it in the given cols
  unless summarized_paged_cols.blank?
    sumarize_collection!(object, summarized_paged_cols, paged_cols_arel, :page)
  end
  unless summarized_all_cols.blank?
    sumarize_collection!(object, summarized_all_cols, all_cols_arel, :all)
  end
end
prepare_settings(logged_user, object, settings, params, per_page = 10, forced_per_page = nil) click to toggle source
# File lib/model_mixins/table_builder_class_methods.rb, line 9
def prepare_settings(logged_user, object, settings, params, per_page = 10, forced_per_page = nil)
  params[:page] = 1 if params[:page].blank?
  params[:order_by] = settings[:default][:order_by] + " " + settings[:default][:order_by_direction] if params[:order_by].blank? && !settings[:default][:order_by].blank? && !settings[:default][:order_by_direction].blank?

  params[:order_by] = settings[:default][:order] if params[:order_by].blank? && !settings[:default][:order].blank?

  # there are allowed per_pages in the settings[:per_page]
  unless settings[:per_page].blank?
    unless params["per_page_chosen"].blank?
      params[:per_page] = settings[:per_page].include?(params["per_page_chosen"].to_i) ? params["per_page_chosen"].to_i : settings[:per_page].first
    end
  end

  if params[:per_page].blank?
    #default per page from Class variable set in initializer
    params[:per_page] = ModelMixins::TableBuilderClassMethods::PER_PAGE if defined?(ModelMixins::TableBuilderClassMethods::PER_PAGE)

    #or with higher priority from table definition
    params[:per_page] = settings[:default][:per_page] if params[:per_page].blank? && !settings[:default][:per_page].blank?
  end
  params[:per_page] = per_page if params[:per_page].blank?
  # forcing per page for print, export of all, etc., there will be maximum, later I can add ___unlimited___
  params[:per_page] = forced_per_page unless forced_per_page.blank?
  per_page = params[:per_page]


  # method below can change this if there were some virtual non exixtent columns
  params[:real_order_by] = params[:order_by]
  check_non_existing_colum_order_by(settings, params)

  not_selected_items = object.filter(object, settings, params, per_page)
  items = not_selected_items.selection(settings)
  if items.respond_to?(:total_pages) && params[:page].to_i > items.total_pages && items.total_pages > 0
    params[:page] = 1
    not_selected_items = object.filter(object, settings, params, per_page)
    items = not_selected_items.selection(settings)
  end

  # todo when template passed, this code is not probably needed
  # the array of items, Will be filled with column method values, formatting values, etc.
  all_items = items.all # maybe can be done more optimal
  all_items_row_ids = all_items.collect { |x| x.row_id }.uniq

  # summarization will be in one query, otherwise it takes a lot of time to do it in many
  summarized_paged_cols = []
  summarized_all_cols = []

  if settings[:template].blank? || settings[:standard_query_processing]
    # initialize another_global_formats,another_formats and column_methods
    another_global_formats = []
    another_formats = []
    column_methods = []
    settings[:columns].each do |col|
      if !col[:summarize_page].blank? && col[:summarize_page]
        # mysql SUM of the collumn on the page
        # passing all_items.total_entries because I don't want it to count again
        if all_items.kind_of?(WillPaginate::Collection)
          # if this is not will paginate collection, it means there is no pagination, so there wont be summary of page
          #col[:summarize_page_value] = sumarize(object, col, object.filter(object, settings, params, per_page, all_items.total_entries).selection(settings))
          summarized_paged_cols << col
        end
      end

      if !col[:summarize_all].blank? && col[:summarize_all]
        # mysql SUM of the collumn off all data
        #col[:summarize_all_value] = sumarize(object, col, object.filter(object, settings, params, false).selection(settings))
        summarized_all_cols << col
      end


      unless col[:global_format_method].blank?
        # ToDo dodelat moznost predani parametru do formatovaci metody
        col[:name] = col[:name].blank? ? "non_existing_column___" + col[:global_format_method] : col[:name]
        another_global_format = {:global_format_method => col[:global_format_method],
                                 :name => col[:name],
                                 :table => col[:table]}
        another_global_formats << another_global_format
      end
      unless col[:format_method].blank?
        col[:name] = col[:name].blank? ? "non_existing_column___" + col[:format_method] : col[:name]
        another_format = {:format_method => col[:format_method],
                          :name => col[:name],
                          :table => col[:table]}
        another_formats << another_format
      end
      unless col[:column_method].blank?
        column_methods << {:column_method => col[:column_method],
                           :name => col[:name],
                           :table => col[:table],
                           :column_class => col[:column_class],
                           :column_params => col[:column_params]
        }
      end
    end

    # making all summarizations in 2 queries
    summarized_paged_cols_arel = nil
    summarized_all_cols_arel = nil

    summarized_paged_cols_arel = object.filter(object, settings, params, per_page, all_items.total_entries).selection(settings) unless summarized_paged_cols.blank?
    summarized_all_cols_arel = object.filter(object, settings, params, false).selection(settings) unless summarized_all_cols.blank?
    make_sumarizations!(object, summarized_paged_cols, summarized_paged_cols_arel, summarized_all_cols, summarized_all_cols_arel)


    # same as template_items below, loads objects so column method are better to use
    # todo think about, but I dont need object, because it's making the same query twice, I just need class and with one outer join it return filtered data, and i include includes to it
    #template_items = object.joins("RIGHT OUTER JOIN (" + not_selected_items.select(settings[:row][:id] + " AS row_id").to_sql + ") temp_template_query ON #{settings[:row][:id]} = temp_template_query.row_id")
    # the AREL with items
    if object.respond_to?(:klass)
      #template_items = object.klass.joins("RIGHT OUTER JOIN (" + items.uniq.to_sql + ") temp_template_query ON #{settings[:row][:id]} = temp_template_query.row_id")
      # more optimalized
      template_items = object.klass.where("#{settings[:row][:id]}" => all_items_row_ids)
    else
      #template_items = object.joins("RIGHT OUTER JOIN (" + items.uniq.to_sql + ") temp_template_query ON #{settings[:row][:id]} = temp_template_query.row_id")
      template_items = object.where("#{settings[:row][:id]}" => all_items_row_ids)
    end

    # loading colors for editable table
    editable_table_load_colors(settings, object, all_items_row_ids)

    template_items = template_items.includes(settings[:includes])

    #template_items.all
    # todo dat do knowledge base, kdyz chci aby fungoval include nesmim volat all
    #template_items.each {|t| t.meeting_registrations.each {|x| puts x.inspect}}

    # calling column methods
    another_columns = {}
    unless column_methods.blank?
      column_method_settings = {:params => params}
      column_methods.each do |column_method|
        column_method_settings[:column_params] = column_method[:column_params]
        #all items == array of array items
        #template items == AREL
        if column_method[:column_class].blank?
          if object.respond_to?(:klass)
            another_columns[column_method[:column_method]] = object.klass.send(column_method[:column_method], logged_user, all_items, template_items, column_method_settings)
          else
            another_columns[column_method[:column_method]] = object.send(column_method[:column_method], logged_user, all_items, template_items, column_method_settings)
          end
        else
          column_method[:column_class] = column_method[:column_class].constantize if column_method[:column_class].kind_of?(String)
          another_columns[column_method[:column_method]] = column_method[:column_class].send(column_method[:column_method], logged_user, all_items, template_items, column_method_settings)
        end
      end
    end

    # updating items by another_global_formats,another_formats, column_methods, summary_methods
    if another_global_formats.blank? && another_formats.blank? && column_methods.blank? &&
        items_array = items
    else
      items_array = []
      all_items.each do |i|
        attrs = i.attributes
        another_global_formats.each do |another_global_format|
          # todo udelat moznost predani dalsich parametru
          case another_global_format[:table]
            when "___sql_expression___"
              col_name = "#{another_global_format[:name]}"
            else
              col_name = "#{another_global_format[:table]}_#{another_global_format[:name]}"
          end
          attrs.merge!({col_name => i.send(another_global_format[:global_format_method].to_sym, attrs[col_name])})
        end
        another_formats.each do |another_format|
          case another_format[:table]
            when "___sql_expression___"
              col_name = "#{another_format[:name]}"
            else
              col_name = "#{another_format[:table]}_#{another_format[:name]}"
          end

          attrs.merge!({col_name => i.send(another_format[:format_method].to_sym, attrs[col_name])})
        end
        column_methods.each do |column_method|
          another_column_row = "-"
          another_column_row = another_columns[column_method[:column_method]][attrs['row_id']] if !another_columns.blank? && !another_columns[column_method[:column_method]].blank? && !another_columns[column_method[:column_method]][attrs['row_id']].blank?
          attrs.merge!({"#{column_method[:table]}_#{column_method[:name]}" => another_column_row})
        end

        items_array << attrs
      end
    end

    settings.merge!({:data => items_array})
  else
    #template_items = object.joins("RIGHT OUTER JOIN (" + not_selected_items.uniq.select(settings[:row][:id] + " AS row_id").to_sql + ") temp_template_query ON #{settings[:row][:id]} = temp_template_query.row_id")
    if object.respond_to?(:klass)
      template_items = object.klass.joins("RIGHT OUTER JOIN (" + items.uniq.to_sql + ") temp_template_query ON #{settings[:row][:id]} = temp_template_query.row_id")
    else
      template_items = object.joins("RIGHT OUTER JOIN (" + items.uniq.to_sql + ") temp_template_query ON #{settings[:row][:id]} = temp_template_query.row_id")
    end

    template_items = template_items.includes(settings[:includes])
    settings.merge!({:data => template_items})
  end

  # summary_methods
  unless settings[:summaries].blank?
    summaries = settings[:summaries]
    summaries.each do |summary|
      summary_settings = {:params => params}
      summary_settings[:summary_params] = summary[:summary_params]

      if summary[:summary_class].blank?
        if object.respond_to?(:klass)
          val = object.klass.send(summary[:summary_method], logged_user, all_items, template_items, object, summary_settings)
        else
          val = object.send(summary[:summary_method], logged_user, all_items, template_items, object, summary_settings)
        end
      else
        summary_class = summary[:summary_class].constantize if summary[:summary_class].kind_of?(String)
        val = summary_class.send(summary[:summary_method], logged_user, all_items, template_items, object, summary_settings)
      end
      if val.kind_of?(Hash)
        summary[:value] = val[:value]
        summary[:class] = val[:class]
      else
        summary[:value] = val
      end
    end

  end


  settings.merge!({:data_paginate => items})
  settings.merge!({:params => params})
  settings
end
process_number_exact_filter(params) click to toggle source
# File lib/model_mixins/table_builder_class_methods.rb, line 386
def process_number_exact_filter(params)
  # this will divide :number_exact filter into find_exact and number_from - number_to filter
  # the condition is look for interval if there is an interval(2 values given) otherwise look for the exact match

  if !params.blank?
    number_exact_from = params['number_exact_from'].blank? ? nil : params['number_exact_from'].dup
    number_exact_to = params['number_exact_to'].blank? ? nil : params['number_exact_to'].dup

    if (!number_exact_from.blank? && !number_exact_to.blank?)
      # if they have whole interval, it will go to number_filter
      number_keys = number_exact_from.keys.delete_if { |x| number_exact_from[x].blank? } &
          number_exact_to.keys.delete_if { |x| number_exact_to[x].blank? }
      number_keys.each do |number_key|
        # move it to number filter
        params['number_from'] ||= {}
        params['number_from'][number_key] = number_exact_from[number_key]
        params['number_to'] ||= {}
        params['number_to'][number_key] = number_exact_to[number_key]

        # and delete it
        number_exact_from.delete(number_key)
        number_exact_to.delete(number_key)
      end
    end

    # the ones with whole interval were removed, I will put the rest in find exact
    if (!number_exact_from.blank?)
      params['find_exact'] ||= {}
      number_exact_from.each_pair do |index, value|
        params['find_exact'][index] = value unless value.blank?
      end
    end

    if (!number_exact_to.blank?)
      params['find_exact'] ||= {}
      number_exact_to.each_pair do |index, value|
        params['find_exact'][index] = value unless value.blank?
      end
    end
  end
  params
end
selection(settings) click to toggle source
# File lib/model_mixins/table_builder_class_methods.rb, line 345
def selection(settings)
  select_string = ""
  settings[:columns].each do |col|
    col[:table] = "___unknown___" if col[:table].blank?
    col[:table] = "___sql_expression___" unless col[:sql_expression].blank?

    if col[:column_method].blank? && col[:row_method].blank? && !col[:name].blank?
      if col[:sql_expression].blank?
        # I am selection col[:name]
        select_string += ", " unless select_string.blank?
        select_string += "#{col[:table]}.#{col[:name]} AS #{col[:table]}_#{col[:name]}"
      else
        # Iam selecting col[:expression] and col[:name] is alias
        # the expression can be sql expression
        select_string += ", " unless select_string.blank?
        select_string += "#{col[:sql_expression]} AS #{col[:name]}"
      end
    end

    # for select more data in combination with filter_method (etc full_name of user))
    if !col[:table].blank? && !col[:select].blank? && !col[:select_as].blank?
      col[:select_as] = col[:table] if col[:select_as].blank?

      col[:select].split(",").each do |one_select|
        one_select.gsub!(" ", "")
        select_string += ", " unless select_string.blank?
        select_string += "#{col[:select_as]}.#{one_select} AS #{col[:select_as]}_#{one_select}"
      end
    end

    # for (agregated data)
    #if (!col[:select_agregated].blank?
  end

  select_string += ", " unless select_string.blank?
  select_string += "#{settings[:row][:id]} AS row_id "


  select(select_string)
end
sumarize(object, col, items) click to toggle source
# File lib/model_mixins/table_builder_class_methods.rb, line 311
def sumarize(object, col, items)
  #method for sumarizing values in column

  if col[:sql_expression].blank?
    col_name = "#{col[:table]}_#{col[:name]}"
  else
    col_name = col[:name]
  end

  if object.respond_to?(:klass)
    mysql_count = object.klass.find_by_sql("SELECT SUM(#{col_name}) AS sum_column FROM (" + items.to_sql + ") count")
  else
    mysql_count = object.find_by_sql("SELECT SUM(#{col_name}) AS sum_column FROM (" + items.to_sql + ") count")
  end

  #count = items.sum(col[:name])
  count = mysql_count.first[:sum_column]

  format_method = nil

  format_method = col[:format_method] unless col[:format_method].blank?
  format_method = col[:global_format_method] unless col[:global_format_method].blank?

  unless format_method.blank?
    if object.respond_to?(:klass)
      count = object.klass.new.send(format_method.to_sym, count)
    else
      count = object.new.send(format_method.to_sym, count)
    end
  end

  count
end
sumarize_collection!(object, cols, items_arel, type) click to toggle source
# File lib/model_mixins/table_builder_class_methods.rb, line 249
def sumarize_collection!(object, cols, items_arel, type)
  # make the col_name aliases and the query
  col_names = {}
  sum_query = ""
  cols.each do |col|
    if col[:sql_expression].blank?
      col_name = "#{col[:table]}_#{col[:name]}"
    else
      col_name = col[:name]
    end

    col_name_alias = col_name + "_sum"

    sum_query += ", " unless sum_query.blank?
    sum_query += "SUM(#{col_name}) AS #{col_name_alias}"
  end

  #make the query
  if object.respond_to?(:klass)
    mysql_sums = object.klass.find_by_sql("SELECT #{sum_query} FROM (" + items_arel.to_sql + ") counts")
  else
    mysql_sums = object.find_by_sql("SELECT #{sum_query} FROM (" + items_arel.to_sql + ") counts")
  end
  sums = mysql_sums.first

  # set the summarization results back to cols
  cols.each do |col|
    if col[:sql_expression].blank?
      col_name = "#{col[:table]}_#{col[:name]}"
    else
      col_name = col[:name]
    end

    col_name_alias = col_name + "_sum"

    # getting summarization value
    sum_value = sums[col_name_alias]

    # formating sum_value, if there is formating method
    format_method = nil
    format_method = col[:format_method] unless col[:format_method].blank?
    format_method = col[:global_format_method] unless col[:global_format_method].blank?

    unless format_method.blank?
      if object.respond_to?(:klass)
        sum_value = object.klass.new.send(format_method.to_sym, sum_value)
      else
        sum_value = object.new.send(format_method.to_sym, sum_value)
      end
    end


    # assigning back to col by type
    case type
      when :all
        col[:summarize_all_value] = sum_value
      when :page
        col[:summarize_page_value] = sum_value
    end
  end
end