jquery-tablesorter-rails-utils 0.0.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 78cbade05c4684cc14f69a730fef1e7dd40ec1b1
4
- data.tar.gz: dc91520ae73b330131ff2e2c8adf1f659f7e6b77
2
+ SHA256:
3
+ metadata.gz: 6d98212066f5ac93fe21031a01671d3ff844b63839b916aa59bdbf83b6c93d9f
4
+ data.tar.gz: 1a54f4773bcae58fe0e44f3aecef78f79908a57d137e90edc7dd9d1a1efc5ac6
5
5
  SHA512:
6
- metadata.gz: d813e7bcdae763cd440088a3d71d37164d9758f5f8f23d11c8dff9328f1811c6dbce53f28771bb592c43bc31748199b84a77e93658460ec2c29c1d51fc8af39c
7
- data.tar.gz: f5eaae71f1dc5fe2e92ec1e2273108ba187dd0c481e8ad84bd5122998e26d17bd9d022358614546afb9b8b1a0fc4b95706d6a7acd8951e86a773a9ddfed5e467
6
+ metadata.gz: a0e372bf08248ffb06ae896fd9c8c182d1da90ed3c947fb5e0c2e9b09168910781926960beb29739d67f7a265e5eeb4f7ff4702d7b3da058058745b51c4b1a88
7
+ data.tar.gz: 8df400686e4d15a9cd0cd33ff70e5182c91aea9fd33e57a399b7470c92130f43ec50833aeccdf28daecc347bdeb011843b7721eed51ad44706fb537320e80036
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
1
  # Change Log
2
2
 
3
- ## 0.1.0 (2016-09-30) (initial release)
3
+ ## 0.2.0 (2020-01-09)
4
+
5
+ ### Important Notice
6
+ This version changes the whole interface of the gem. In case you used it, it will require changes.
7
+ Also please note that the documentation wasn't changed yet.
8
+
9
+ ### Changed
10
+ * Mostly everything.
11
+ * Rails 6 support
12
+
13
+ ## 0.1.0 (2016-09-28) (initial release)
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in jquery-tablesorter-rails-utils.gemspec
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Jquery::Tablesorter::Rails::Utils
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/jquery-tablesorter-rails-utils.svg)](https://badge.fury.io/rb/jquery-tablesorter-rails-utils)
4
+
3
5
  Helpful (hopefully! ;-) ) additions for jQuery tablesorter (only support for [Mottie's fork] targeted) when working with rails.
4
6
 
5
7
  While still in early development - which might bring breaking changes with new releases - it is meant to provide helpful utilities for jquery-tablesorter in rails. At the current state of development it only supports a mechanism to help to work with Ajax based tables.
@@ -26,7 +28,9 @@ Or install it yourself as:
26
28
 
27
29
  $ gem install jquery-tablesorter-rails-utils
28
30
 
29
- ## Usage
31
+ ## Usage (Attention: OUTDATED!)
32
+
33
+ !!! The following information might not fully apply to version 0.2.0 !!!
30
34
 
31
35
  ### Module: Ajax
32
36
 
data/Rakefile CHANGED
@@ -1,2 +1,4 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
2
4
  task default: :spec
@@ -1,5 +1,6 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'jquery-tablesorter/rails-utils/version'
5
6
 
@@ -14,18 +15,19 @@ Gem::Specification.new do |spec|
14
15
  spec.homepage = 'https://github.com/themilkman/jquery-tablesorter-rails-utils'
15
16
  spec.license = 'MIT'
16
17
 
17
- spec.required_ruby_version = '>= 1.9.3'
18
18
 
19
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ spec.required_ruby_version = '>= 2.4.0'
20
+
21
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
22
  f.match(%r{^(test|spec|features)/})
21
23
  end
22
24
 
23
25
  spec.require_paths = ['lib']
24
26
 
25
- spec.add_dependency 'activerecord', '>= 4.0', '< 6.0'
26
- spec.add_dependency 'activesupport', '>= 4.0', '< 6.0'
27
- spec.add_dependency 'actionview', '>= 4.0', '< 6.0'
28
27
  spec.add_dependency 'pg'
28
+ spec.add_dependency 'actionview', '>= 5.0', '< 7.0'
29
+ spec.add_dependency 'activerecord', '>= 5.0', '< 7.0'
30
+ spec.add_dependency 'activesupport', '>= 5.0', '< 7.0'
29
31
 
30
32
  spec.add_development_dependency 'bundler', '~> 1.13'
31
33
  spec.add_development_dependency 'rake', '~> 10.0'
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'jquery-tablesorter/rails-utils/version'
2
4
  require 'jquery-tablesorter/rails-utils/ajax'
@@ -1,20 +1,6 @@
1
- # Adds mechanisms to work with Ajax based tables and tablesorter.
2
- # Current limitions (extract ;-P):
3
- # * It does not support sorting by multiple columns.
4
- # * Currently only PostgreSQL is supported
5
- #
6
- # Usage:
7
- # Includet this module in your controller and call methods in your query-action,
8
- # where the results can be used to build the response.
9
- #
10
- # Further ToDos/plans/ideas/dreams:
11
- # * There might be a possibility to pass a block for each column-operation such
12
- # as filtering or sorting and allow more dynamic work. This might happen before or better
13
- # instead the standard processing. (partly done with the filter_mapping filter-parameter)
14
- # * Maybe it'd be possible to allow multi-column sorting somehow.
15
- # * In some cases it could make sense not to cast all columns to strings/varchars. So, an optionally passed
16
- # type for a column might get evaluated/used in a different manner. (done for DateTime)
1
+ # frozen_string_literal: true
17
2
 
3
+ # Adds mechanisms to work with Ajax based tables and tablesorter.
18
4
  module JqueryTablesorter
19
5
  module RailsUtils
20
6
  module Ajax
@@ -1,39 +1,52 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Controller concern to help with ajax jquery tablesorter requests.
2
4
  # It handles sorting and filtering.
3
-
5
+ # Current limitions (extract ;-P):
6
+ # * It does not support sorting by multiple columns.
7
+ #
8
+ # Usage:
9
+ # Include module in controller and call methods in query-action,
10
+ # where the results can be used to build the response.
11
+ #
12
+ # Further ToDos/plans/ideas/dreams:
13
+ # * Also, there might be a possibility to pass a block for each column-operation such
14
+ # as filtering or sorting and allow more dynamic work. This might happen before or better
15
+ # instead the standard processing.
16
+ # * Maybe it'd be possible to allow multi-column sorting somehow.
17
+ # * In some cases it could make sense not to cast all columns to strings/varchars. So, an optionally passed
18
+ # type for a column might get evaluated/used in a different manner.
19
+ # * Evaluate if the position of a column should be passed to the columns (in other words: useful?!)
4
20
  module JqueryTablesorter
5
21
  module RailsUtils
6
22
  module Ajax
7
23
  module ActionController
8
24
  extend ActiveSupport::Concern
9
25
 
10
-
11
26
  # A generalized method to handle tablesorter queries. It's meant to be used in the corresponding
12
27
  # Controller action. Params:
13
28
  # clazz: The model's primary class
14
29
  # base_query: If there are any relevant joins or so -> pass the AR relation here
15
30
  # partial (optional): path to the partial to be rendered
16
- def create_query_html_response(base_query, partial: 'row')
17
- resp_data = ts_ajax_handler.query_data(base_query)
31
+ def create_query_html_response(base_query, partial: 'row', locals: {})
32
+ resp_data = ts_ajax_handler.query_data(base_query)
33
+ records = resp_data.delete(:records)
34
+ resp_data[:data] = render_response_html(records, partial: partial, locals: locals)
18
35
 
19
- records = resp_data.delete(:records)
20
- resp_data[:data] = render_response_html(records, partial: partial)
21
-
22
- return resp_data
36
+ resp_data
23
37
  end
24
38
 
25
39
  private
26
40
 
27
41
  # Render the html rows for the given records and an optional named partial.
28
42
  # Returns HTML string or nil
29
- def render_response_html(records, partial: 'row' )
30
- output = render_to_string partial: partial, locals: { records: records }
43
+ def render_response_html(records, partial: 'row', locals: {} )
44
+ output = render_to_string(partial: partial, locals: { records: records }.merge(locals))
31
45
 
32
- unless records.any? # if the query had 0 results, it will return a string which has let jquery crash
33
- output = nil
34
- end
46
+ # if the query has no results, it will return a string which causes jquery to crash
47
+ output = nil unless records.any?
35
48
 
36
- return output
49
+ output
37
50
  end
38
51
 
39
52
  def ts_ajax_handler
@@ -41,11 +54,12 @@ module JqueryTablesorter
41
54
  end
42
55
 
43
56
  def tablesorter_params
44
- params.permit(:page, :size, :controller, :action, :query, :sort, :filter,
45
- { sort: params[:sort].try(:keys) },
46
- { filter: params[:filter].try(:keys) })
57
+ params.permit(
58
+ :page, :size, :controller, :action, :query, :sort, :filter,
59
+ { sort: params[:sort].try(:keys) },
60
+ { filter: params[:filter].try(:keys) }
61
+ )
47
62
  end
48
-
49
63
  end
50
64
  end
51
65
  end
@@ -1,60 +1,61 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JqueryTablesorter
2
4
  module RailsUtils
3
5
  module Ajax
4
- # Represents a table sorting Filter. In most cases this is also a column
5
- # in your table, but might als be a global/external filter.
6
+ # Represents a table sorting Filter.
6
7
  class Filter
7
- # Name of the column in the DB. Used for queries, but may also be :all for glob. filters.
8
- attr_accessor :column_name
9
- # Class of the base model.
10
- attr_accessor :model
11
- # If you need to join, this is your relation table
12
- attr_accessor :join_rel
13
- # An external table column to be used with join.
14
- attr_accessor :external_column
15
- # If a having clase is required, pass it here. This will change the controll flow on
16
- # filter-/sorting.
17
- attr_accessor :having_clause
18
- # Optional data type of the column. This might be used to make queries more flexible.
19
- # For examaple, if DateTime is passed, it will strip away milliseconds from query.
20
- attr_accessor :data_type
21
- # Optional boolean filter if the given filter is a global filter or not.
22
- attr_accessor :global_filter
23
- # Optional index requested by tablesorter, needed for glob. filters.
24
- attr_accessor :position
25
- # Optional block to modify the real input of filters to match UI (e.g. Input: 'Iceland' => DB: 'is')
26
- # This block has to return an array which will be used for an IN-Query. Thus, the current implementation
27
- # depends on an 1:1 match.
28
- attr_accessor :filter_mapping
29
-
30
- def initialize(column_name, model_clazz, opts = {})
31
- @column_name = column_name
32
- @model = model_clazz
33
- @position = opts[:position]
34
- @join_rel = opts[:join_rel]
35
- @external_column = opts[:external_column]
36
- @having_clause = opts[:having_clause]
37
- @data_type = opts[:data_type]
38
- @global_filter = opts[:global_filter]
39
- @filter_mapping = opts[:filter_mapping]
40
- end
41
-
42
- def global_filter?
43
- @global_filter || false
44
- end
45
-
46
- def name
47
- self.column_name
48
- end
49
-
50
- def model_class
51
- self.model
52
- end
53
-
54
- def external?
55
- external_column.present?
8
+ attr_reader :position, :options
9
+
10
+ def initialize(position, options = {})
11
+ @position = position || (options[:global] ? 999 : nil)
12
+ @options = options
13
+ end
14
+
15
+ # dummy filter that will does nothing
16
+ def noop?
17
+ !!@options[:noop]
18
+ end
19
+
20
+ # filter that is only applied on global filtering
21
+ def global?
22
+ @options[:global] || false
23
+ end
24
+
25
+ # data type of column for special handling
26
+ def data_type
27
+ @options[:data_type].presence
28
+ end
29
+
30
+ # model class that has the specified column
31
+ def klass
32
+ @options[:class].presence
56
33
  end
57
34
 
35
+ # column that should be filtered on
36
+ def column
37
+ @options[:column].presence
38
+ end
39
+
40
+ # proc for filtering/mapping values
41
+ def values
42
+ @options[:values].presence
43
+ end
44
+
45
+ # proc for custom query modifications
46
+ def query
47
+ @options[:query].presence
48
+ end
49
+
50
+ # proc for custom column sorter
51
+ def sorter_query
52
+ @options[:sorter_query].presence
53
+ end
54
+
55
+ # string with sql having condition
56
+ def having
57
+ @options[:having].presence
58
+ end
58
59
  end
59
60
  end
60
61
  end
@@ -1,19 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JqueryTablesorter
2
4
  module RailsUtils
3
5
  module Ajax
4
6
  # Class used by ActionController concern. Encapsulates query logic.
5
7
  # For further documentation see ajax-module.
6
8
  class Handler
7
-
8
9
  def initialize(tablesorter_params)
9
10
  @ts_params = tablesorter_params
10
11
  end
11
12
 
12
13
  # Define the table structure
13
- def create_filter_info(column_name, model_clazz, filter_opts = {})
14
- filter = Filter.new(column_name, model_clazz, filter_opts)
14
+ def create_filter_info(position, options = {})
15
+ filter = Filter.new(position, options)
16
+
15
17
  ajax_filters << filter
16
- return filter
18
+
19
+ filter
17
20
  end
18
21
 
19
22
  # Load data for the given tablesorter params in a controller action
@@ -24,40 +27,40 @@ module JqueryTablesorter
24
27
  # filtered_rows: How many records are left after filtering
25
28
  # records: An collection with the resulting records
26
29
  def query_data(base_query)
27
- @query = base_query
28
-
29
- result = Hash.new
30
+ query = base_query
31
+ result = Hash.new
30
32
 
31
33
  # Filters
32
- @query = apply_filters(@query, tablesorter_params)
34
+ query = apply_filters(query, tablesorter_params)
33
35
 
34
36
  # Calculate row counts
35
- rec_counts = record_counts(base_query, @query)
37
+ rec_counts = record_counts(base_query, query)
36
38
  result[:filtered_rows] = rec_counts[:filtered_rows]
37
39
  result[:total_rows] = rec_counts[:total_rows]
38
40
 
39
41
  # Handle paging afterwards
40
- @query = handle_pagination(@query, tablesorter_params, result)
42
+ query = handle_pagination(query, tablesorter_params, result)
41
43
 
42
44
  # Sorting
43
- @query = apply_sorting(@query, tablesorter_params)
45
+ query = apply_sorting(query, tablesorter_params)
44
46
 
45
- result[:records] = @query
47
+ result[:records] = query
46
48
 
47
- return result
49
+ result
48
50
  end
49
51
 
52
+ private
53
+
50
54
  # Calulate count of all and filtered records
51
55
  # Params:
52
56
  # model_query: The base query of the current selection
53
57
  # filtered_query: The filtered query (relation with applied tablesorter filters)
54
58
  def record_counts(model_query, filtered_query)
55
- counts = Hash.new
56
- total = model_query.distinct.count(:id)
59
+ counts = Hash.new
60
+ total = model_query.distinct.count(:id)
57
61
 
58
- if total.is_a?(Hash) # Handle results of joined queries. This feels a little bit hacky.
59
- total = total.keys.length
60
- end
62
+ # Handle results of joined queries. This feels a little bit hacky.
63
+ total = total.keys.length if total.is_a?(Hash)
61
64
 
62
65
  counts[:total_rows] = total
63
66
 
@@ -65,183 +68,148 @@ module JqueryTablesorter
65
68
  # Count again if additional filters were applied (fires a query)
66
69
  cnt = filtered_query.count("#{model_query.table_name}.id")
67
70
 
68
- if cnt.is_a?(Hash) # Handle results of having-queries. This feels a little bit hacky.
69
- cnt = cnt.keys.length
70
- end
71
+ # Handle results of having-queries. This feels a little bit hacky.
72
+ cnt = cnt.keys.length if cnt.is_a?(Hash)
73
+
71
74
  counts[:filtered_rows] = cnt
72
75
  else
73
76
  counts[:filtered_rows] = total # There wasn't any reduction.
74
77
  end
75
78
 
76
- return counts
79
+ counts
77
80
  end
78
81
 
82
+ # add filter query to sql
83
+ def apply_filter(query, filter, value)
84
+ return [query] if query.blank? || filter.blank? || value.blank?
85
+ return [query] if filter.noop?
79
86
 
80
- # let every special case be handled within that block.
81
- # block should remove the values from the params parameter to allow regular processing.
82
- def apply_filters(record_relation, filter_params)
83
- splat_global_filter(filter_params)
84
- record_relation = apply_global_filters(record_relation, filter_params)
87
+ klass = filter.klass || query.klass
88
+ column = filter.column
89
+ value = filter.values.call(value) if filter.values.present?
85
90
 
86
- # iterate over all filter inputs
87
- (filter_params[:filter] || {}).each do |filter_index, filter_value|
88
- sel_col = ajax_filters[filter_index.to_i]
89
- next if sel_col.blank?
90
-
91
- clazz = sel_col.model
92
- selected_column = sel_col.name
93
-
94
- if sel_col.external? # query an external model
95
- ext_query = "LOWER(#{sel_col.join_rel}.#{sel_col.external_column}::varchar) LIKE LOWER(?)"
96
- record_relation = record_relation.where(ext_query, "%#{filter_value}%")
97
-
98
- elsif sel_col.having_clause
99
- clause = sel_col.having_clause
100
- record_relation = record_relation.having("LOWER((#{clause})::varchar) LIKE ?", "%#{filter_value}%")
101
-
102
- elsif sel_col.filter_mapping # there were modifications on the query
103
- target_col = "#{clazz.table_name}.#{selected_column}"
104
- values = sel_col.filter_mapping.call(filter_value)
105
- # Maybe we could use an SIMILAR TO query for this.
106
- record_relation = record_relation.where("LOWER(#{target_col}::varchar) IN (?)", values )
107
-
108
- else # directly on current model
109
- target_col = "#{clazz.table_name}.#{selected_column}"
110
- if sel_col.data_type == DateTime
111
- target_col = "date_trunc('minute', #{target_col})"
91
+ queries = []
92
+
93
+ if column.present?
94
+ target_column = "#{klass.table_name}.#{column}"
95
+
96
+ if filter.data_type == DateTime
97
+ target_column = "date_trunc('second', #{target_column})"
98
+ end
99
+
100
+ vals = Array(value)
101
+ value = []
102
+ q = []
103
+
104
+ vals.each do |val|
105
+ if klass.columns_hash[column.to_s] && klass.columns_hash[column.to_s].type == :integer && !(val.to_s.strip =~ /\A\d+\Z/)
106
+ q << '0 = 1'
107
+ else
108
+ q << "LOWER(#{target_column}::varchar) LIKE LOWER(?)"
109
+ value << "%#{val}%"
112
110
  end
113
- record_relation = record_relation.where("LOWER(#{target_col}::varchar) LIKE LOWER(?)", "%#{filter_value}%" )
114
111
  end
115
112
 
113
+ queries << "(#{q.join(' OR ')})" if q.any?
114
+ elsif filter.query.present?
115
+ query, query_list, value_list = filter.query.call(query, value)
116
+ queries = Array(query_list)
117
+ value = Array(value_list)
118
+ elsif filter.having.present?
119
+ query = query.having("LOWER((#{filter.having})::varchar) LIKE ?", "%#{Array(value).first}%")
116
120
  end
117
121
 
118
- return record_relation
122
+ [query, queries, value]
119
123
  end
120
124
 
121
- # Sort the passed relation by the tablesorter-sorting.
122
- def apply_sorting(record_relation, sort_params)
123
- (sort_params[:sort] || {}).each do |sort_index, order|
124
- order = (order.to_i % 2 == 0) ? :asc : :desc
125
- sel_col = ajax_filters[sort_index.to_i]
125
+ # apply global filter value for all column filters
126
+ def apply_global_filters(query, filter_params)
127
+ value = filter_params[:filter][999.to_s] rescue nil
126
128
 
127
- if sel_col.external?
128
- order_query = [sel_col.join_rel, sel_col.external_column].compact.join('.')
129
- record_relation = record_relation.order("#{order_query} #{order}")
129
+ return query if value.blank?
130
130
 
131
- elsif sel_col.having_clause
132
- # If there is a having_clause, use the column name w/o tablename
133
- record_relation = record_relation.order("#{sel_col.name} #{order} NULLS LAST")
131
+ queries = []
132
+ values = []
134
133
 
135
- else
136
- order_query = [sel_col.model.table_name, sel_col.name].compact.join('.')
137
- record_relation = record_relation.order("#{order_query} #{order} NULLS LAST")
138
- end
134
+ # iterate over all filter inputs
135
+ ajax_filters.each do |filter|
136
+ next if filter.blank?
137
+ next if filter.having.present?
138
+
139
+ query, q, v = apply_filter(query, filter, value)
139
140
 
141
+ next if q.blank?
142
+
143
+ queries += Array(q)
144
+ values += Array(v) unless v.nil?
140
145
  end
141
146
 
142
- return record_relation
147
+ query.where(queries.join(' OR '), *values)
143
148
  end
144
149
 
145
- # Paginiation/the amount of visible rows in the table (per page)
146
- def handle_pagination(query, ts_params, result)
147
- # Tablesorter submits row count or simply 'all'. If user requests more rows
148
- # than available do nothing.
149
- return query if ( (ts_params[:size] == 'all') || (ts_params[:size].to_i >= result[:total_rows]) )
150
+ # apply individual column filters
151
+ def apply_filters(query, filter_params)
152
+ query = apply_global_filters(query, filter_params)
150
153
 
151
- query = query
152
- .limit(ts_params[:size].to_i)
153
- .offset(ts_params[:size].to_i * ts_params[:page].to_i)
154
+ queries = []
155
+ values = []
154
156
 
155
- return query
156
- end
157
+ # iterate over all filter inputs
158
+ (filter_params[:filter] || {}).each do |idx, value|
159
+ ajax_filters.select { |f| f.position == idx.to_i }.each do |filter|
160
+ next if filter.blank?
161
+ next if filter.global?
157
162
 
158
- # Array with all currently configured Filter-Objects
159
- def ajax_filters
160
- @_ajax_table_filters ||= []
161
- end
163
+ query, q, v = apply_filter(query, filter, value)
162
164
 
163
- private
165
+ next if q.blank?
164
166
 
165
- def tablesorter_params
166
- @ts_params
167
+ queries += Array(q)
168
+ values += Array(v) unless v.nil?
169
+ end
170
+ end
171
+
172
+ query.where(queries.join(' AND '), *values)
167
173
  end
168
174
 
169
- # Iterate over all columns with the (previous in *splat_global_filter* initialized)
170
- # global filter value
171
- def apply_global_filters(record_relation, filter_params)
172
- # TODO Wouldn't it be smarter to make query an array and join it by ' OR '?
173
- query = ''
174
- filter_values = []
175
-
176
- (filter_params[:global_filter] || {}).each do |filter_index, filter_value|
177
- sel_col = ajax_filters[filter_index.to_i]
178
- next if sel_col.blank?
179
-
180
- clazz = sel_col.model
181
- selected_column = sel_col.name
182
- table_name = clazz.table_name
183
-
184
- if sel_col.external? # Query an external model
185
- query << "LOWER(#{sel_col.join_rel}.#{sel_col.external_column}::varchar) LIKE LOWER(?) OR "
186
- filter_values << "%#{filter_value}%"
187
-
188
- elsif sel_col.filter_mapping # there were modifications on the query
189
- target_col = "#{clazz.table_name}.#{selected_column}"
190
- values = sel_col.filter_mapping.call(filter_value)
191
- # Maybe we could use an SIMILAR TO query for this.
192
- query << "LOWER(#{target_col}::varchar) IN (?) OR "
193
- filter_values << values
194
-
195
- elsif sel_col.having_clause
196
- # Having clauses will create an extra query to select IDs of base-table records
197
- # an add them into the main query as IN <ids>.
198
- # If there is a having_clause, use the column name only w/o tablename.
199
- clause = "LOWER(#{sel_col.having_clause}::varchar) LIKE LOWER(?)"
200
- filter_values << record_relation.having(clause, "%#{filter_value}%")
201
- .pluck(:id)
202
- query << "#{table_name}.id IN (?) OR "
175
+ # Sort the passed relation by the tablesorter-sorting.
176
+ def apply_sorting(query, sort_params)
177
+ (sort_params[:sort] || {}).each do |idx, order|
178
+ order = (order.to_i % 2 == 0) ? :asc : :desc
179
+ filter = ajax_filters.find { |f| f.position == idx.to_i }
203
180
 
204
- else
205
- target_col = "#{table_name}.#{selected_column}"
181
+ next if filter.blank?
206
182
 
207
- if sel_col.data_type == DateTime # Special handling for Dates -> strip away millisecs
208
- target_col = "date_trunc('second', #{target_col})"
209
- end
183
+ klass = filter.klass || query.klass
184
+ column = filter.column
210
185
 
211
- query << "LOWER(#{target_col}::varchar) LIKE LOWER(?) OR "
212
- filter_values << "%#{filter_value}%"
186
+ if filter.sorter_query.present?
187
+ query = filter.sorter_query.call(query, order)
188
+ else
189
+ query = query.reorder("#{klass.table_name}.#{column} #{order} NULLS LAST")
213
190
  end
214
191
  end
215
192
 
216
- query = query.chomp(' OR ') # remove the last OR
193
+ query
194
+ end
217
195
 
218
- return record_relation.where(query, *filter_values)
196
+ # Paginiation/the amount of visible rows in the table (per page)
197
+ def handle_pagination(query, ts_params, result)
198
+ # Tablesorter submits row count or simply 'all'. If user requests more rows
199
+ # than available do nothing.
200
+ return query if (ts_params[:size] == 'all') || (ts_params[:size].to_i >= result[:total_rows])
219
201
 
202
+ query.limit(ts_params[:size].to_i).offset(ts_params[:size].to_i * ts_params[:page].to_i)
220
203
  end
221
204
 
222
- # If any global filter value (the user input) is found (which currently is asumed to the last),
223
- # take this input and add it to a global_filter subkey with the corresponding index of each
224
- # not global-filter column. Thus, later the may be used to check all coulmns for the given
225
- # input.
226
- def splat_global_filter(filter_params)
227
- # Global filter params is assumed to be at the last index
228
- global_filter = ajax_filters.find { |c| c.global_filter? }
229
- return unless global_filter
230
-
231
- global_filter_value = filter_params.dig(:filter, global_filter.position.to_s)
232
- return if global_filter_value.nil?
233
-
234
- filter_params[:global_filter] ||= {}
235
- ajax_filters.each_with_index do |col, idx|
236
- next if (col.nil? || col.global_filter?)
237
- # Add search query for each (non-global) value
238
- filter_params[:global_filter][idx.to_s] = global_filter_value
239
- end
240
-
241
- # Remove the global filter from the params
242
- filter_params[:filter].delete(global_filter.position.to_s)
205
+ # Array with all currently configured Filter-Objects
206
+ def ajax_filters
207
+ @_ajax_table_filters ||= []
243
208
  end
244
209
 
210
+ def tablesorter_params
211
+ @ts_params
212
+ end
245
213
  end
246
214
  end
247
215
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JqueryTablesorter
2
4
  module RailsUtils
3
5
  MAJOR = 0
4
- MINOR = 0
5
- TINY = 1
6
+ MINOR = 2
7
+ TINY = 0
6
8
 
7
9
  VERSION = [MAJOR, MINOR, TINY].compact.join('.')
8
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jquery-tablesorter-rails-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik-B. Ernst
@@ -9,82 +9,82 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-09-30 00:00:00.000000000 Z
12
+ date: 2020-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: activerecord
15
+ name: pg
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '4.0'
21
- - - "<"
22
- - !ruby/object:Gem::Version
23
- version: '6.0'
20
+ version: '0'
24
21
  type: :runtime
25
22
  prerelease: false
26
23
  version_requirements: !ruby/object:Gem::Requirement
27
24
  requirements:
28
25
  - - ">="
29
26
  - !ruby/object:Gem::Version
30
- version: '4.0'
31
- - - "<"
32
- - !ruby/object:Gem::Version
33
- version: '6.0'
27
+ version: '0'
34
28
  - !ruby/object:Gem::Dependency
35
- name: activesupport
29
+ name: actionview
36
30
  requirement: !ruby/object:Gem::Requirement
37
31
  requirements:
38
32
  - - ">="
39
33
  - !ruby/object:Gem::Version
40
- version: '4.0'
34
+ version: '5.0'
41
35
  - - "<"
42
36
  - !ruby/object:Gem::Version
43
- version: '6.0'
37
+ version: '7.0'
44
38
  type: :runtime
45
39
  prerelease: false
46
40
  version_requirements: !ruby/object:Gem::Requirement
47
41
  requirements:
48
42
  - - ">="
49
43
  - !ruby/object:Gem::Version
50
- version: '4.0'
44
+ version: '5.0'
51
45
  - - "<"
52
46
  - !ruby/object:Gem::Version
53
- version: '6.0'
47
+ version: '7.0'
54
48
  - !ruby/object:Gem::Dependency
55
- name: actionview
49
+ name: activerecord
56
50
  requirement: !ruby/object:Gem::Requirement
57
51
  requirements:
58
52
  - - ">="
59
53
  - !ruby/object:Gem::Version
60
- version: '4.0'
54
+ version: '5.0'
61
55
  - - "<"
62
56
  - !ruby/object:Gem::Version
63
- version: '6.0'
57
+ version: '7.0'
64
58
  type: :runtime
65
59
  prerelease: false
66
60
  version_requirements: !ruby/object:Gem::Requirement
67
61
  requirements:
68
62
  - - ">="
69
63
  - !ruby/object:Gem::Version
70
- version: '4.0'
64
+ version: '5.0'
71
65
  - - "<"
72
66
  - !ruby/object:Gem::Version
73
- version: '6.0'
67
+ version: '7.0'
74
68
  - !ruby/object:Gem::Dependency
75
- name: pg
69
+ name: activesupport
76
70
  requirement: !ruby/object:Gem::Requirement
77
71
  requirements:
78
72
  - - ">="
79
73
  - !ruby/object:Gem::Version
80
- version: '0'
74
+ version: '5.0'
75
+ - - "<"
76
+ - !ruby/object:Gem::Version
77
+ version: '7.0'
81
78
  type: :runtime
82
79
  prerelease: false
83
80
  version_requirements: !ruby/object:Gem::Requirement
84
81
  requirements:
85
82
  - - ">="
86
83
  - !ruby/object:Gem::Version
87
- version: '0'
84
+ version: '5.0'
85
+ - - "<"
86
+ - !ruby/object:Gem::Version
87
+ version: '7.0'
88
88
  - !ruby/object:Gem::Dependency
89
89
  name: bundler
90
90
  requirement: !ruby/object:Gem::Requirement
@@ -144,15 +144,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
144
  requirements:
145
145
  - - ">="
146
146
  - !ruby/object:Gem::Version
147
- version: 1.9.3
147
+ version: 2.4.0
148
148
  required_rubygems_version: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
153
  requirements: []
154
- rubyforge_project:
155
- rubygems_version: 2.5.1
154
+ rubygems_version: 3.1.2
156
155
  signing_key:
157
156
  specification_version: 4
158
157
  summary: Some helpers to work with jQuery tablesorter and Ruby on Rails