Class: JqueryTablesorter::RailsUtils::Ajax::Handler

Inherits:
Object
  • Object
show all
Defined in:
lib/jquery-tablesorter/rails-utils/ajax/handler.rb

Overview

Class used by ActionController concern. Encapsulates query logic. For further documentation see ajax-module.

Instance Method Summary collapse

Constructor Details

#initialize(tablesorter_params) ⇒ Handler

Returns a new instance of Handler.



8
9
10
# File 'lib/jquery-tablesorter/rails-utils/ajax/handler.rb', line 8

def initialize(tablesorter_params)
  @ts_params = tablesorter_params
end

Instance Method Details

#ajax_filtersObject

Array with all currently configured Filter-Objects



159
160
161
# File 'lib/jquery-tablesorter/rails-utils/ajax/handler.rb', line 159

def ajax_filters
  @_ajax_table_filters ||= []
end

#apply_filters(record_relation, filter_params) ⇒ Object

let every special case be handled within that block. block should remove the values from the params parameter to allow regular processing.



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/jquery-tablesorter/rails-utils/ajax/handler.rb', line 82

def apply_filters(record_relation, filter_params)
  splat_global_filter(filter_params)
  record_relation = apply_global_filters(record_relation, filter_params)

  # iterate over all filter inputs
  (filter_params[:filter] || {}).each do |filter_index, filter_value|
    sel_col = ajax_filters[filter_index.to_i]
    next if sel_col.blank?

    clazz           = sel_col.model
    selected_column = sel_col.name

    if sel_col.external? # query an external model
      ext_query       = "LOWER(#{sel_col.join_rel}.#{sel_col.external_column}::varchar) LIKE LOWER(?)"
      record_relation = record_relation.where(ext_query, "%#{filter_value}%")

    elsif sel_col.having_clause
      clause          = sel_col.having_clause
      record_relation = record_relation.having("LOWER((#{clause})::varchar) LIKE ?", "%#{filter_value}%")

    elsif sel_col.filter_mapping # there were modifications on the query
      target_col      = "#{clazz.table_name}.#{selected_column}"
      values          = sel_col.filter_mapping.call(filter_value)
      # Maybe we could use an SIMILAR TO query for this.
      record_relation = record_relation.where("LOWER(#{target_col}::varchar) IN (?)", values )

    else # directly on current model
      target_col = "#{clazz.table_name}.#{selected_column}"
      if sel_col.data_type == DateTime
        target_col = "date_trunc('minute', #{target_col})"
      end
      record_relation = record_relation.where("LOWER(#{target_col}::varchar) LIKE LOWER(?)", "%#{filter_value}%" )
    end

  end

  return record_relation
end

#apply_sorting(record_relation, sort_params) ⇒ Object

Sort the passed relation by the tablesorter-sorting.



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/jquery-tablesorter/rails-utils/ajax/handler.rb', line 122

def apply_sorting(record_relation, sort_params)
  (sort_params[:sort] || {}).each do |sort_index, order|
    order   = (order.to_i % 2 == 0) ? :asc : :desc
    sel_col = ajax_filters[sort_index.to_i]

    if sel_col.external?
      order_query     = [sel_col.join_rel, sel_col.external_column].compact.join('.')
      record_relation = record_relation.order("#{order_query} #{order}")

    elsif sel_col.having_clause
      # If there is a having_clause, use the column name w/o tablename
      record_relation = record_relation.order("#{sel_col.name} #{order} NULLS LAST")

    else
      order_query     = [sel_col.model.table_name, sel_col.name].compact.join('.')
      record_relation = record_relation.order("#{order_query} #{order} NULLS LAST")
    end

  end

  return record_relation
end

#create_filter_info(column_name, model_clazz, filter_opts = {}) ⇒ Object

Define the table structure



13
14
15
16
17
# File 'lib/jquery-tablesorter/rails-utils/ajax/handler.rb', line 13

def create_filter_info(column_name, model_clazz, filter_opts = {})
  filter = Filter.new(column_name, model_clazz, filter_opts)
  ajax_filters << filter
  return filter
end

#handle_pagination(query, ts_params, result) ⇒ Object

Paginiation/the amount of visible rows in the table (per page)



146
147
148
149
150
151
152
153
154
155
156
# File 'lib/jquery-tablesorter/rails-utils/ajax/handler.rb', line 146

def handle_pagination(query, ts_params, result)
  # Tablesorter submits row count or simply 'all'. If user requests more rows
  # than available do nothing.
  return query if ( (ts_params[:size] == 'all') || (ts_params[:size].to_i >= result[:total_rows]) )

  query = query
              .limit(ts_params[:size].to_i)
              .offset(ts_params[:size].to_i * ts_params[:page].to_i)

  return query
end

#query_data(base_query) ⇒ Object

Load data for the given tablesorter params in a controller action Params: base_query: If there are any relevant joins or so -> pass the AR relation here Returns a hash with: total_rows: How many records are there available filtered_rows: How many records are left after filtering records: An collection with the resulting records



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/jquery-tablesorter/rails-utils/ajax/handler.rb', line 26

def query_data(base_query)
  @query      = base_query

  result      = Hash.new

  # Filters
  @query = apply_filters(@query, tablesorter_params)

  # Calculate row counts
  rec_counts             = record_counts(base_query, @query)
  result[:filtered_rows] = rec_counts[:filtered_rows]
  result[:total_rows]    = rec_counts[:total_rows]

  # Handle paging afterwards
  @query = handle_pagination(@query, tablesorter_params, result)

  # Sorting
  @query = apply_sorting(@query, tablesorter_params)

  result[:records] = @query

  return result
end

#record_counts(model_query, filtered_query) ⇒ Object

Calulate count of all and filtered records Params: model_query: The base query of the current selection filtered_query: The filtered query (relation with applied tablesorter filters)



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/jquery-tablesorter/rails-utils/ajax/handler.rb', line 54

def record_counts(model_query, filtered_query)
  counts              = Hash.new
  total               = model_query.distinct.count(:id)

  if total.is_a?(Hash) # Handle results of joined queries. This feels a little bit hacky.
    total = total.keys.length
  end

  counts[:total_rows] = total

  if tablesorter_params[:filter]
    # Count again if additional filters were applied (fires a query)
    cnt = filtered_query.count("#{model_query.table_name}.id")

    if cnt.is_a?(Hash) # Handle results of having-queries. This feels a little bit hacky.
      cnt = cnt.keys.length
    end
    counts[:filtered_rows] = cnt
  else
    counts[:filtered_rows] = total # There wasn't any reduction.
  end

  return counts
end