jquery-tablesorter-rails-utils 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +133 -0
- data/Rakefile +2 -0
- data/jquery-tablesorter-rails-utils.gemspec +32 -0
- data/lib/jquery-tablesorter-rails-utils.rb +2 -0
- data/lib/jquery-tablesorter/rails-utils/ajax.rb +26 -0
- data/lib/jquery-tablesorter/rails-utils/ajax/action_controller.rb +52 -0
- data/lib/jquery-tablesorter/rails-utils/ajax/filter.rb +61 -0
- data/lib/jquery-tablesorter/rails-utils/ajax/handler.rb +248 -0
- data/lib/jquery-tablesorter/rails-utils/version.rb +9 -0
- metadata +159 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 78cbade05c4684cc14f69a730fef1e7dd40ec1b1
|
4
|
+
data.tar.gz: dc91520ae73b330131ff2e2c8adf1f659f7e6b77
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d813e7bcdae763cd440088a3d71d37164d9758f5f8f23d11c8dff9328f1811c6dbce53f28771bb592c43bc31748199b84a77e93658460ec2c29c1d51fc8af39c
|
7
|
+
data.tar.gz: f5eaae71f1dc5fe2e92ec1e2273108ba187dd0c481e8ad84bd5122998e26d17bd9d022358614546afb9b8b1a0fc4b95706d6a7acd8951e86a773a9ddfed5e467
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2016 Erik-B. Ernst
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Jquery::Tablesorter::Rails::Utils
|
2
|
+
|
3
|
+
Helpful (hopefully! ;-) ) additions for jQuery tablesorter (only support for [Mottie's fork] targeted) when working with rails.
|
4
|
+
|
5
|
+
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.
|
6
|
+
You have a helpful idea/code snippet for something which makes it easier to work with tablesorter and rails? Cool, feel free to create a pull request!
|
7
|
+
|
8
|
+
For further information how to work with jQuery tablesorter I recommend the excellent [documentation] in [Mottie's fork].
|
9
|
+
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Please note: Tablesorter has to be installed separately from this gem. You may use my packaged version ([jquery-tablesorter-gem]) or any other way to add it to your project.
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
~~~ruby
|
18
|
+
gem 'jquery-tablesorter-rails-utils'
|
19
|
+
~~~
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install jquery-tablesorter-rails-utils
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
### Module: Ajax
|
32
|
+
|
33
|
+
The following sections shows an example how to use the Ajax module. It currently only supports PostgreSQL.
|
34
|
+
|
35
|
+
So, to query rendered HTML rows of your Foo model you may do:
|
36
|
+
|
37
|
+
In your controller (don't forget to add your routes!):
|
38
|
+
|
39
|
+
~~~ruby
|
40
|
+
|
41
|
+
class FooController < ApplicationController
|
42
|
+
include JqueryTablesorter::RailsUtils::Ajax::ActionController
|
43
|
+
|
44
|
+
# Ajax query for the foo list rows
|
45
|
+
def query_list
|
46
|
+
base_query = Foo.my_scope
|
47
|
+
|
48
|
+
foo_columns()
|
49
|
+
resp = create_query_response(base_query, partial: 'my_partial_foo_row')
|
50
|
+
|
51
|
+
render json: resp
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def foo_columns
|
57
|
+
ts_ajax_handler.create_filter_info(:name, Foo)
|
58
|
+
ts_ajax_handler.create_filter_info(:other_attribute_name_of_foo, Foo)
|
59
|
+
# Let's say, there is a global filter, too. The position is the param
|
60
|
+
# tablesorter submits on an request.
|
61
|
+
ts_ajax_handler.create_filter_info(:all, Foo, { global_filter: true, position: 5 })
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
~~~
|
66
|
+
|
67
|
+
In the .coffee file you prepare your tablesorter instance and may add code like this:
|
68
|
+
|
69
|
+
~~~coffee
|
70
|
+
|
71
|
+
$('#my_ajax_table').tablesorter(
|
72
|
+
# ...
|
73
|
+
).tablesorterPager(
|
74
|
+
# your pager settings..
|
75
|
+
# if data tag is given, handle this table as ajax table
|
76
|
+
if query_url = current_table.data('query-url')
|
77
|
+
ajax_pager =
|
78
|
+
processAjaxOnInit: true
|
79
|
+
ajaxUrl: query_url
|
80
|
+
ajaxError: null
|
81
|
+
ajaxObject:
|
82
|
+
dataType: 'json'
|
83
|
+
ajaxProcessing: (result, table, xhr) ->
|
84
|
+
if result
|
85
|
+
result.total = result['total_rows']
|
86
|
+
result.filteredRows = result['filtered_rows']
|
87
|
+
if result.hasOwnProperty('data')
|
88
|
+
result.rows = $(result.data) # rendered <tr>s
|
89
|
+
return result
|
90
|
+
)
|
91
|
+
~~~
|
92
|
+
|
93
|
+
In your view, the table partials could look like:
|
94
|
+
|
95
|
+
~~~haml
|
96
|
+
|
97
|
+
%table#my_ajax_table{ 'data-query-url': 'foo/query?&page={page}&size={size}&{sortList:sort}&{filterList:filter}' }
|
98
|
+
%thead
|
99
|
+
%tr
|
100
|
+
%th= name
|
101
|
+
%th= other_attribute_name_of_foo
|
102
|
+
%tfoot
|
103
|
+
= render partial: 'your_footer_partial'
|
104
|
+
%tbody
|
105
|
+
~~~
|
106
|
+
|
107
|
+
And the partial for the table rows:
|
108
|
+
|
109
|
+
~~~haml
|
110
|
+
|
111
|
+
= records.each do |foo|
|
112
|
+
%tr
|
113
|
+
%td= foo.name
|
114
|
+
%td= foo.other_attribute_name_of_foo
|
115
|
+
~~~
|
116
|
+
|
117
|
+
|
118
|
+
## Licensing
|
119
|
+
|
120
|
+
* Licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) license.
|
121
|
+
|
122
|
+
## Contributing
|
123
|
+
|
124
|
+
1. Fork it
|
125
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
126
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
127
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
128
|
+
5. Create new Pull Request
|
129
|
+
|
130
|
+
|
131
|
+
[Mottie's fork]: https://github.com/Mottie/tablesorter
|
132
|
+
[documentation]: http://mottie.github.com/tablesorter/docs/index.html
|
133
|
+
[jquery-tablesorter-gem]: https://github.com/themilkman/jquery-tablesorter-rails
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'jquery-tablesorter/rails-utils/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'jquery-tablesorter-rails-utils'
|
8
|
+
spec.version = JqueryTablesorter::RailsUtils::VERSION
|
9
|
+
spec.authors = ['Erik-B. Ernst', 'Thomas Halter']
|
10
|
+
spec.email = ['github@black-milk.de']
|
11
|
+
|
12
|
+
spec.summary = %q{Some helpers to work with jQuery tablesorter and Ruby on Rails}
|
13
|
+
spec.description = %q{Some helpers to work with jQuery tablesorter and Ruby on Rails.}
|
14
|
+
spec.homepage = 'https://github.com/themilkman/jquery-tablesorter-rails-utils'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.required_ruby_version = '>= 1.9.3'
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
20
|
+
f.match(%r{^(test|spec|features)/})
|
21
|
+
end
|
22
|
+
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
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
|
+
spec.add_dependency 'pg'
|
29
|
+
|
30
|
+
spec.add_development_dependency 'bundler', '~> 1.13'
|
31
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
32
|
+
end
|
@@ -0,0 +1,26 @@
|
|
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)
|
17
|
+
|
18
|
+
module JqueryTablesorter
|
19
|
+
module RailsUtils
|
20
|
+
module Ajax
|
21
|
+
require 'jquery-tablesorter/rails-utils/ajax/filter'
|
22
|
+
require 'jquery-tablesorter/rails-utils/ajax/handler'
|
23
|
+
require 'jquery-tablesorter/rails-utils/ajax/action_controller'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# Controller concern to help with ajax jquery tablesorter requests.
|
2
|
+
# It handles sorting and filtering.
|
3
|
+
|
4
|
+
module JqueryTablesorter
|
5
|
+
module RailsUtils
|
6
|
+
module Ajax
|
7
|
+
module ActionController
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
|
11
|
+
# A generalized method to handle tablesorter queries. It's meant to be used in the corresponding
|
12
|
+
# Controller action. Params:
|
13
|
+
# clazz: The model's primary class
|
14
|
+
# base_query: If there are any relevant joins or so -> pass the AR relation here
|
15
|
+
# 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)
|
18
|
+
|
19
|
+
records = resp_data.delete(:records)
|
20
|
+
resp_data[:data] = render_response_html(records, partial: partial)
|
21
|
+
|
22
|
+
return resp_data
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Render the html rows for the given records and an optional named partial.
|
28
|
+
# Returns HTML string or nil
|
29
|
+
def render_response_html(records, partial: 'row' )
|
30
|
+
output = render_to_string partial: partial, locals: { records: records }
|
31
|
+
|
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
|
35
|
+
|
36
|
+
return output
|
37
|
+
end
|
38
|
+
|
39
|
+
def ts_ajax_handler
|
40
|
+
@_ts_ajax_handler ||= Handler.new(tablesorter_params)
|
41
|
+
end
|
42
|
+
|
43
|
+
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) })
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module JqueryTablesorter
|
2
|
+
module RailsUtils
|
3
|
+
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
|
+
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?
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
module JqueryTablesorter
|
2
|
+
module RailsUtils
|
3
|
+
module Ajax
|
4
|
+
# Class used by ActionController concern. Encapsulates query logic.
|
5
|
+
# For further documentation see ajax-module.
|
6
|
+
class Handler
|
7
|
+
|
8
|
+
def initialize(tablesorter_params)
|
9
|
+
@ts_params = tablesorter_params
|
10
|
+
end
|
11
|
+
|
12
|
+
# 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)
|
15
|
+
ajax_filters << filter
|
16
|
+
return filter
|
17
|
+
end
|
18
|
+
|
19
|
+
# Load data for the given tablesorter params in a controller action
|
20
|
+
# Params:
|
21
|
+
# base_query: If there are any relevant joins or so -> pass the AR relation here
|
22
|
+
# Returns a hash with:
|
23
|
+
# total_rows: How many records are there available
|
24
|
+
# filtered_rows: How many records are left after filtering
|
25
|
+
# records: An collection with the resulting records
|
26
|
+
def query_data(base_query)
|
27
|
+
@query = base_query
|
28
|
+
|
29
|
+
result = Hash.new
|
30
|
+
|
31
|
+
# Filters
|
32
|
+
@query = apply_filters(@query, tablesorter_params)
|
33
|
+
|
34
|
+
# Calculate row counts
|
35
|
+
rec_counts = record_counts(base_query, @query)
|
36
|
+
result[:filtered_rows] = rec_counts[:filtered_rows]
|
37
|
+
result[:total_rows] = rec_counts[:total_rows]
|
38
|
+
|
39
|
+
# Handle paging afterwards
|
40
|
+
@query = handle_pagination(@query, tablesorter_params, result)
|
41
|
+
|
42
|
+
# Sorting
|
43
|
+
@query = apply_sorting(@query, tablesorter_params)
|
44
|
+
|
45
|
+
result[:records] = @query
|
46
|
+
|
47
|
+
return result
|
48
|
+
end
|
49
|
+
|
50
|
+
# Calulate count of all and filtered records
|
51
|
+
# Params:
|
52
|
+
# model_query: The base query of the current selection
|
53
|
+
# filtered_query: The filtered query (relation with applied tablesorter filters)
|
54
|
+
def record_counts(model_query, filtered_query)
|
55
|
+
counts = Hash.new
|
56
|
+
total = model_query.distinct.count(:id)
|
57
|
+
|
58
|
+
if total.is_a?(Hash) # Handle results of joined queries. This feels a little bit hacky.
|
59
|
+
total = total.keys.length
|
60
|
+
end
|
61
|
+
|
62
|
+
counts[:total_rows] = total
|
63
|
+
|
64
|
+
if tablesorter_params[:filter]
|
65
|
+
# Count again if additional filters were applied (fires a query)
|
66
|
+
cnt = filtered_query.count("#{model_query.table_name}.id")
|
67
|
+
|
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
|
+
counts[:filtered_rows] = cnt
|
72
|
+
else
|
73
|
+
counts[:filtered_rows] = total # There wasn't any reduction.
|
74
|
+
end
|
75
|
+
|
76
|
+
return counts
|
77
|
+
end
|
78
|
+
|
79
|
+
|
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)
|
85
|
+
|
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})"
|
112
|
+
end
|
113
|
+
record_relation = record_relation.where("LOWER(#{target_col}::varchar) LIKE LOWER(?)", "%#{filter_value}%" )
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
return record_relation
|
119
|
+
end
|
120
|
+
|
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]
|
126
|
+
|
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}")
|
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")
|
134
|
+
|
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
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
return record_relation
|
143
|
+
end
|
144
|
+
|
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
|
+
|
151
|
+
query = query
|
152
|
+
.limit(ts_params[:size].to_i)
|
153
|
+
.offset(ts_params[:size].to_i * ts_params[:page].to_i)
|
154
|
+
|
155
|
+
return query
|
156
|
+
end
|
157
|
+
|
158
|
+
# Array with all currently configured Filter-Objects
|
159
|
+
def ajax_filters
|
160
|
+
@_ajax_table_filters ||= []
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def tablesorter_params
|
166
|
+
@ts_params
|
167
|
+
end
|
168
|
+
|
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 "
|
203
|
+
|
204
|
+
else
|
205
|
+
target_col = "#{table_name}.#{selected_column}"
|
206
|
+
|
207
|
+
if sel_col.data_type == DateTime # Special handling for Dates -> strip away millisecs
|
208
|
+
target_col = "date_trunc('second', #{target_col})"
|
209
|
+
end
|
210
|
+
|
211
|
+
query << "LOWER(#{target_col}::varchar) LIKE LOWER(?) OR "
|
212
|
+
filter_values << "%#{filter_value}%"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
query = query.chomp(' OR ') # remove the last OR
|
217
|
+
|
218
|
+
return record_relation.where(query, *filter_values)
|
219
|
+
|
220
|
+
end
|
221
|
+
|
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)
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
metadata
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jquery-tablesorter-rails-utils
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Erik-B. Ernst
|
8
|
+
- Thomas Halter
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2016-09-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '4.0'
|
21
|
+
- - "<"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '6.0'
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '4.0'
|
31
|
+
- - "<"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '6.0'
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: activesupport
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.0'
|
41
|
+
- - "<"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '6.0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '4.0'
|
51
|
+
- - "<"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '6.0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: actionview
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '4.0'
|
61
|
+
- - "<"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '6.0'
|
64
|
+
type: :runtime
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '4.0'
|
71
|
+
- - "<"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '6.0'
|
74
|
+
- !ruby/object:Gem::Dependency
|
75
|
+
name: pg
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
type: :runtime
|
82
|
+
prerelease: false
|
83
|
+
version_requirements: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
- !ruby/object:Gem::Dependency
|
89
|
+
name: bundler
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '1.13'
|
95
|
+
type: :development
|
96
|
+
prerelease: false
|
97
|
+
version_requirements: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '1.13'
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: rake
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '10.0'
|
109
|
+
type: :development
|
110
|
+
prerelease: false
|
111
|
+
version_requirements: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '10.0'
|
116
|
+
description: Some helpers to work with jQuery tablesorter and Ruby on Rails.
|
117
|
+
email:
|
118
|
+
- github@black-milk.de
|
119
|
+
executables: []
|
120
|
+
extensions: []
|
121
|
+
extra_rdoc_files: []
|
122
|
+
files:
|
123
|
+
- CHANGELOG.md
|
124
|
+
- Gemfile
|
125
|
+
- LICENSE
|
126
|
+
- README.md
|
127
|
+
- Rakefile
|
128
|
+
- jquery-tablesorter-rails-utils.gemspec
|
129
|
+
- lib/jquery-tablesorter-rails-utils.rb
|
130
|
+
- lib/jquery-tablesorter/rails-utils/ajax.rb
|
131
|
+
- lib/jquery-tablesorter/rails-utils/ajax/action_controller.rb
|
132
|
+
- lib/jquery-tablesorter/rails-utils/ajax/filter.rb
|
133
|
+
- lib/jquery-tablesorter/rails-utils/ajax/handler.rb
|
134
|
+
- lib/jquery-tablesorter/rails-utils/version.rb
|
135
|
+
homepage: https://github.com/themilkman/jquery-tablesorter-rails-utils
|
136
|
+
licenses:
|
137
|
+
- MIT
|
138
|
+
metadata: {}
|
139
|
+
post_install_message:
|
140
|
+
rdoc_options: []
|
141
|
+
require_paths:
|
142
|
+
- lib
|
143
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: 1.9.3
|
148
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
requirements: []
|
154
|
+
rubyforge_project:
|
155
|
+
rubygems_version: 2.5.1
|
156
|
+
signing_key:
|
157
|
+
specification_version: 4
|
158
|
+
summary: Some helpers to work with jQuery tablesorter and Ruby on Rails
|
159
|
+
test_files: []
|