table_sortable 0.2.0 → 0.3.0
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 +4 -4
- data/.idea/.rakeTasks +1 -1
- data/.idea/table_sortable.iml +7 -20
- data/README.md +243 -3
- data/lib/table_sortable/column/filter.rb +7 -5
- data/lib/table_sortable/column/sorter.rb +2 -2
- data/lib/table_sortable/column.rb +14 -3
- data/lib/table_sortable/concerns/proc.rb +24 -8
- data/lib/table_sortable/controller.rb +31 -12
- data/lib/table_sortable/railtie.rb +9 -0
- data/lib/table_sortable/version.rb +1 -1
- data/lib/table_sortable/view_helpers.rb +67 -0
- data/lib/table_sortable.rb +3 -5
- data/spec/concerns/proc_class_spec.rb +2 -2
- data/spec/controllers/test_controller_spec.rb +3 -0
- data/spec/lib/table_sortable/concerns/proc_spec.rb +11 -16
- data/spec/lib/table_sortable/controller_spec.rb +11 -10
- data/spec/support/models/user.rb +7 -1
- data/table_sortable.gemspec +4 -2
- metadata +30 -11
- data/app/helpers/table_sortable_helper.rb +0 -15
- data/app/views/table_sortable/_columns.slim +0 -3
- data/app/views/table_sortable/_field.slim +0 -1
- data/app/views/table_sortable/_header.slim +0 -2
- data/app/views/table_sortable/_headers.slim +0 -3
- data/app/views/table_sortable/_pager.slim +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb3b153304402456414d809c4ebb4f20598912e1
|
4
|
+
data.tar.gz: 1bb7b72fbc3b9052bbd93da005e81f4a37dcf43d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54e7d680129b165ffe901e66135fb9ada66214c6696eb5b9b7e3d8c3f702cb161443bf53f769e737216e5eb62645c07cac1f4dceb5179263b06a9fc6ce5f733e
|
7
|
+
data.tar.gz: 762d3c06491fcc61f56c069b72e8a1820740bb987b3ee897b8f2dae52b48cebdfd62afede63175f8f70f11fe7270a15027c84288e9550fc1740dc1bed3b3d4f9
|
data/.idea/.rakeTasks
CHANGED
@@ -4,4 +4,4 @@ You are allowed to:
|
|
4
4
|
1. Remove rake task
|
5
5
|
2. Add existing rake tasks
|
6
6
|
To add existing rake tasks automatically delete this file and reload the project.
|
7
|
-
--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build table_sortable-0.
|
7
|
+
--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build table_sortable-0.2.0.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Remove any temporary products" fullCmd="clean" taksId="clean" /><RakeTask description="Remove any generated files" fullCmd="clobber" taksId="clobber" /><RakeTask description="Build and install table_sortable-0.2.0.gem into system gems" fullCmd="install" taksId="install" /><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="Build and install table_sortable-0.2.0.gem into system gems without network access" fullCmd="install:local" taksId="local" /></RakeGroup><RakeTask description="Create tag v0.2.0 and build and push table_sortable-0.2.0.gem to Rubygems" fullCmd="release[remote]" taksId="release[remote]" /><RakeTask description="Run tests" fullCmd="test" taksId="test" /><RakeTask description="" fullCmd="default" taksId="default" /><RakeTask description="" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
|
data/.idea/table_sortable.iml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
<module type="RUBY_MODULE" version="4">
|
3
3
|
<component name="ModuleRunConfigurationManager">
|
4
|
-
<configuration default="false" name="All specs in spec: table_sortable" type="RSpecRunConfigurationType" factoryName="RSpec"
|
4
|
+
<configuration default="false" name="All specs in spec: table_sortable" type="RSpecRunConfigurationType" factoryName="RSpec">
|
5
5
|
<predefined_log_file id="RUBY_RSPEC" enabled="true" />
|
6
6
|
<module name="table_sortable" />
|
7
7
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
|
@@ -34,7 +34,7 @@
|
|
34
34
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="FULL_BACKTRACE" VALUE="false" />
|
35
35
|
<method />
|
36
36
|
</configuration>
|
37
|
-
<configuration default="false" name="Run spec '
|
37
|
+
<configuration default="false" name="Run spec 'filter_spec': table_sortable" type="RSpecRunConfigurationType" factoryName="RSpec">
|
38
38
|
<predefined_log_file id="RUBY_RSPEC" enabled="true" />
|
39
39
|
<module name="table_sortable" />
|
40
40
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
|
@@ -53,7 +53,7 @@
|
|
53
53
|
</COVERAGE_PATTERN>
|
54
54
|
</EXTENSION>
|
55
55
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="TESTS_FOLDER_PATH" VALUE="" />
|
56
|
-
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="TEST_SCRIPT_PATH" VALUE="$MODULE_DIR$/spec/lib/table_sortable/
|
56
|
+
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="TEST_SCRIPT_PATH" VALUE="$MODULE_DIR$/spec/lib/table_sortable/column/filter_spec.rb" />
|
57
57
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="SPEC_RUNNER_PATH" VALUE="" />
|
58
58
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="TEST_FILE_MASK" VALUE="**/*_spec.rb" />
|
59
59
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="SPEC_EXAMPLE_NAME" VALUE="" />
|
@@ -67,7 +67,7 @@
|
|
67
67
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="FULL_BACKTRACE" VALUE="false" />
|
68
68
|
<method />
|
69
69
|
</configuration>
|
70
|
-
<configuration default="false" name="Run spec '
|
70
|
+
<configuration default="false" name="Run spec 'proc_spec': table_sortable" type="RSpecRunConfigurationType" factoryName="RSpec">
|
71
71
|
<predefined_log_file id="RUBY_RSPEC" enabled="true" />
|
72
72
|
<module name="table_sortable" />
|
73
73
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
|
@@ -86,7 +86,7 @@
|
|
86
86
|
</COVERAGE_PATTERN>
|
87
87
|
</EXTENSION>
|
88
88
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="TESTS_FOLDER_PATH" VALUE="" />
|
89
|
-
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="TEST_SCRIPT_PATH" VALUE="$MODULE_DIR$/spec/lib/table_sortable/
|
89
|
+
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="TEST_SCRIPT_PATH" VALUE="$MODULE_DIR$/spec/lib/table_sortable/concerns/proc_spec.rb" />
|
90
90
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="SPEC_RUNNER_PATH" VALUE="" />
|
91
91
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="TEST_FILE_MASK" VALUE="**/*_spec.rb" />
|
92
92
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="SPEC_EXAMPLE_NAME" VALUE="" />
|
@@ -100,7 +100,7 @@
|
|
100
100
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="FULL_BACKTRACE" VALUE="false" />
|
101
101
|
<method />
|
102
102
|
</configuration>
|
103
|
-
<configuration default="false" name="TableSortable::Controller filter_and_sort filters using a single filter: table_sortable" type="RSpecRunConfigurationType" factoryName="RSpec"
|
103
|
+
<configuration default="false" name="TableSortable::Controller filter_and_sort filters using a single filter: table_sortable" type="RSpecRunConfigurationType" factoryName="RSpec">
|
104
104
|
<predefined_log_file id="RUBY_RSPEC" enabled="true" />
|
105
105
|
<module name="table_sortable" />
|
106
106
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
|
@@ -133,7 +133,7 @@
|
|
133
133
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="FULL_BACKTRACE" VALUE="false" />
|
134
134
|
<method />
|
135
135
|
</configuration>
|
136
|
-
<configuration default="false" name="TableSortable::Controller filter_and_sort sorts a record set based on the column to sort: table_sortable" type="RSpecRunConfigurationType" factoryName="RSpec"
|
136
|
+
<configuration default="false" name="TableSortable::Controller filter_and_sort sorts a record set based on the column to sort: table_sortable" type="RSpecRunConfigurationType" factoryName="RSpec">
|
137
137
|
<predefined_log_file id="RUBY_RSPEC" enabled="true" />
|
138
138
|
<module name="table_sortable" />
|
139
139
|
<RSPEC_RUN_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
|
@@ -174,11 +174,8 @@
|
|
174
174
|
</content>
|
175
175
|
<orderEntry type="jdk" jdkName="RVM: ruby-2.4.1 [tablesortable]" jdkType="RUBY_SDK" />
|
176
176
|
<orderEntry type="sourceFolder" forTests="false" />
|
177
|
-
<orderEntry type="library" scope="PROVIDED" name="actioncable (v5.1.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
178
|
-
<orderEntry type="library" scope="PROVIDED" name="actionmailer (v5.1.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
179
177
|
<orderEntry type="library" scope="PROVIDED" name="actionpack (v5.1.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
180
178
|
<orderEntry type="library" scope="PROVIDED" name="actionview (v5.1.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
181
|
-
<orderEntry type="library" scope="PROVIDED" name="activejob (v5.1.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
182
179
|
<orderEntry type="library" scope="PROVIDED" name="activemodel (v5.1.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
183
180
|
<orderEntry type="library" scope="PROVIDED" name="activerecord (v5.1.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
184
181
|
<orderEntry type="library" scope="PROVIDED" name="activesupport (v5.1.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
@@ -190,20 +187,14 @@
|
|
190
187
|
<orderEntry type="library" scope="PROVIDED" name="erubi (v1.6.0, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
191
188
|
<orderEntry type="library" scope="PROVIDED" name="factory_girl (v4.8.0, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
192
189
|
<orderEntry type="library" scope="PROVIDED" name="factory_girl_rails (v4.8.0, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
193
|
-
<orderEntry type="library" scope="PROVIDED" name="globalid (v0.4.0, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
194
190
|
<orderEntry type="library" scope="PROVIDED" name="i18n (v0.8.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
195
191
|
<orderEntry type="library" scope="PROVIDED" name="loofah (v2.0.3, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
196
|
-
<orderEntry type="library" scope="PROVIDED" name="mail (v2.6.5, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
197
192
|
<orderEntry type="library" scope="PROVIDED" name="method_source (v0.8.2, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
198
|
-
<orderEntry type="library" scope="PROVIDED" name="mime-types (v3.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
199
|
-
<orderEntry type="library" scope="PROVIDED" name="mime-types-data (v3.2016.0521, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
200
193
|
<orderEntry type="library" scope="PROVIDED" name="mini_portile2 (v2.1.0, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
201
194
|
<orderEntry type="library" scope="PROVIDED" name="minitest (v5.10.2, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
202
|
-
<orderEntry type="library" scope="PROVIDED" name="nio4r (v2.1.0, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
203
195
|
<orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.7.2, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
204
196
|
<orderEntry type="library" scope="PROVIDED" name="rack (v2.0.3, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
205
197
|
<orderEntry type="library" scope="PROVIDED" name="rack-test (v0.6.3, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
206
|
-
<orderEntry type="library" scope="PROVIDED" name="rails (v5.1.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
207
198
|
<orderEntry type="library" scope="PROVIDED" name="rails-dom-testing (v2.0.3, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
208
199
|
<orderEntry type="library" scope="PROVIDED" name="rails-html-sanitizer (v1.0.3, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
209
200
|
<orderEntry type="library" scope="PROVIDED" name="railties (v5.1.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
@@ -213,13 +204,9 @@
|
|
213
204
|
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.6.0, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
214
205
|
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.6.0, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
215
206
|
<orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.6.0, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
216
|
-
<orderEntry type="library" scope="PROVIDED" name="sprockets (v3.7.1, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
217
|
-
<orderEntry type="library" scope="PROVIDED" name="sprockets-rails (v3.2.0, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
218
207
|
<orderEntry type="library" scope="PROVIDED" name="sqlite3 (v1.3.13, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
219
208
|
<orderEntry type="library" scope="PROVIDED" name="thor (v0.19.4, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
220
209
|
<orderEntry type="library" scope="PROVIDED" name="thread_safe (v0.3.6, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
221
210
|
<orderEntry type="library" scope="PROVIDED" name="tzinfo (v1.2.3, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
222
|
-
<orderEntry type="library" scope="PROVIDED" name="websocket-driver (v0.6.5, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
223
|
-
<orderEntry type="library" scope="PROVIDED" name="websocket-extensions (v0.1.2, RVM: ruby-2.4.1 [tablesortable]) [gem]" level="application" />
|
224
211
|
</component>
|
225
212
|
</module>
|
data/README.md
CHANGED
@@ -135,13 +135,253 @@ That's it! The results fetched from the server are now filtered, sorted and pagi
|
|
135
135
|
|
136
136
|
For full documentation of the usage of tableSorter.js please go [here](https://mottie.github.io/tablesorter/docs/index.html) for the very popular fork by mottie, or [here](http://tablesorter.com/docs/) for the original version of the plugin.
|
137
137
|
|
138
|
-
Of course there are many more configuration options that make TableSortable flexible and adaptable. For those, please see [advanced configuration](#advanced-configuration)
|
138
|
+
Of course there are many more configuration options that make TableSortable flexible and adaptable. For those, please see [advanced configuration](#advanced-configuration).
|
139
139
|
|
140
140
|
## Advanced Configuration
|
141
|
-
|
141
|
+
|
142
|
+
TableSortable has several advanced configuration settings, which allow for a more fine-grained control over its behaviour.
|
143
|
+
|
144
|
+
- [define_column](#define_column)
|
145
|
+
- [define_column_order](#define_column_order)
|
146
|
+
- [define_column_offset](#define_column_offset)
|
147
|
+
|
148
|
+
#### define_column
|
149
|
+
|
150
|
+
TableSortable lets you define the columns one by one with many custom attributes, using the `define_column` method.
|
151
|
+
```ruby
|
152
|
+
#controllers/users_controller.rb
|
153
|
+
class UsersController < ApplicationController
|
154
|
+
include TableSortable
|
155
|
+
|
156
|
+
define_column :full_name,
|
157
|
+
value: -> (user) {"#{user.first_name} #{user.last_name}"}
|
158
|
+
define_column :email
|
159
|
+
end
|
160
|
+
```
|
161
|
+
##### Syntax: `define_column column_name, [arguments]`
|
162
|
+
|
163
|
+
- `column_name` <sub>(required)</sub>
|
164
|
+
A symbol representing the column_name. Can be anything, but should usually be the same as the column name.
|
165
|
+
- `arguments` <sub>(optional)</sub>
|
166
|
+
- `value: (symbol|proc)`
|
167
|
+
<sub>default: same as column name</sub>
|
168
|
+
Accepts either a symbol representing a method that the record responds to, like an ActiveRecord attribute,
|
169
|
+
or a proc the returns the record's value. for example:
|
170
|
+
```ruby
|
171
|
+
define_column :full_name,
|
172
|
+
value: -> (user) {"#{user.first_name} #{user.last_name}"}
|
173
|
+
```
|
174
|
+
- `content: (symbol|proc)`
|
175
|
+
<sub>default: same as value</sub>
|
176
|
+
Works the same way as `value`, but allows specifying a different value to be displayed in the table cells.
|
177
|
+
The difference between `value` and `content` is that the former determines the value by which the scope will be filtered and sorted,
|
178
|
+
while the latter only affects the displayed cell contents.
|
179
|
+
```ruby
|
180
|
+
define_column :full_name,
|
181
|
+
value: -> (user) {"#{user.first_name} #{user.last_name}"},
|
182
|
+
content: -> (user) {"#{user.last_name}, #{user.first_name}"}
|
183
|
+
```
|
184
|
+
- `label: (string)`
|
185
|
+
<sub>default: 'Titleized' version of the column name</sub>
|
186
|
+
Allows specifying a string to be used as the column label, displayed at the table header.
|
187
|
+
- `placeholder: (string|false)`
|
188
|
+
<sub>default: same as label</sub>
|
189
|
+
Allows specifying a string to be used as a placeholder for the column's filter input field.
|
190
|
+
You may also specify `false`, in which case no placeholder will be displayed.
|
191
|
+
- `filter: (proc|false)`
|
192
|
+
<sub>default: free case-insensitive text search on the column's value</sub>
|
193
|
+
By default, the column will be filtered according to the column's value. However, you may specify a proc to perform the search on that column.
|
194
|
+
The proc itself can contain either ActiveRecord operations (eg. `where`) or array operations (eg. `select`),
|
195
|
+
and will be passed the current filter query when run.
|
196
|
+
```ruby
|
197
|
+
define_column :full_name,
|
198
|
+
filter: ->(query) {where('LOWER(CONCAT(first_name," ", last_name)) LIKE (?)', "%#{query.downcase}%")}
|
199
|
+
```
|
200
|
+
If no filtering is to be performed on that column you can set it to `false`. When using TableSortable's [view helpers](#view-helpers),
|
201
|
+
this also means that no filter input will be shown on that column.
|
202
|
+
- `filter_method: (:array|:active_record)`
|
203
|
+
<sub>default: automatically detects method based on the record given</sub>
|
204
|
+
Determines whether the default filter function relies on an ActiveRecord `where` method or an Array `select` method.
|
205
|
+
When no method and no filters are supplied, TableSortable will check if the column_name corresponds to a database column of the record.
|
206
|
+
If it does, it will use an ActiveRecord `where` method, otherwise it will perform an array `select` operation.
|
207
|
+
_Only applies when no `filter` option has been specified._
|
208
|
+
- `:array` <sub>(default)</sub>
|
209
|
+
Filter using the `select` method. While being slower, it selects based on the column's value, whatever it might be, and so fits every scenario.
|
210
|
+
- `:active_record`
|
211
|
+
Filter using the `where` method. While being faster, it only applies to cases where the column name matches the database column name.
|
212
|
+
- `filter_initial_value: (string)`
|
213
|
+
<sub>default: nil</sub>
|
214
|
+
You may specify an initial filter query for each column.
|
215
|
+
- `sort: (proc|false)`
|
216
|
+
<sub>default: sorting based on the column's value</sub>
|
217
|
+
By default, the record set will be sorted according to the selected column's value.
|
218
|
+
However, you may specify a proc to perform the sorting when this column is selected as the sort base.
|
219
|
+
The proc itself can contain either ActiveRecord operations (eg. `order`) or array operations (eg. `sort`),
|
220
|
+
and will be passed the current sort order as a symbol (`:asc` or `:desc`) when run.
|
221
|
+
```ruby
|
222
|
+
define_column :full_name,
|
223
|
+
sort: -> (sort_order) { sort{ |a,b| (sort_order == :asc ? a : b) <=> (sort_order == :asc ? b : a) } }
|
224
|
+
```
|
225
|
+
If no sorting is to be performed based on that column you can set it to `false`. When using TableSortable's [view helpers](#view-helpers),
|
226
|
+
this also means that no sorting handle will be shown on the client side on that column as well.
|
227
|
+
- `sort_method: (:array|:active_record)`
|
228
|
+
<sub>default: :array</sub>
|
229
|
+
Determines whether the default sort function relies on an ActiveRecord `order` method or an Array `sort` method.
|
230
|
+
When no method and no filters are supplied, TableSortable will check if the column_name corresponds to a database column of the record.
|
231
|
+
If it does, it will use an ActiveRecord `order` method, otherwise it will perform an array `sort` operation.
|
232
|
+
_Only applies when no `sort` option has been specified._
|
233
|
+
- `:array` <sub>(default)</sub>
|
234
|
+
Sort using the `sort` method. While being slower, it sorts based on the column's value, whatever it might be, and so fits every scenario.
|
235
|
+
- `:active_record`
|
236
|
+
Sort using the `order` method. While being faster, it only applies to cases where the column name matches the database column name.
|
237
|
+
- `template: (string)`
|
238
|
+
<sub>default: same as column_name</sub>
|
239
|
+
Allows setting a custom template name to look for when rendering the header or column contents. For more information see [view helpers](#view-helpers).
|
240
|
+
|
241
|
+
##### Dynamic Column Definitions
|
242
|
+
|
243
|
+
If the column definitions themselves need to be dynamic (eg. if you're using
|
244
|
+
dynamic fields in your model) you can also use `define column` in a `before action` callback like this
|
245
|
+
```ruby
|
246
|
+
#controllers/users_controller.rb
|
247
|
+
|
248
|
+
before_action :define_columns
|
249
|
+
|
250
|
+
private
|
251
|
+
|
252
|
+
def define_columns
|
253
|
+
@user.custom_fields.each do |cf|
|
254
|
+
define_column cf,
|
255
|
+
value: -> (user) {user.get_custom_field(cf)}
|
256
|
+
end
|
257
|
+
end
|
258
|
+
```
|
259
|
+
|
260
|
+
#### define_column_order
|
261
|
+
Columns are displayed in the order they are defined using `define_method`. If you wish, you may override this order by specifying your own using the `define_column_order` method.
|
262
|
+
It also allows hiding columns that you need to include in the filtering and sorting process, eg. when you want to have an external search box filtering based on a column that you don't necessarily want to display.
|
263
|
+
##### Syntax: `define_column_order column1, [column2], [column3] ...`
|
264
|
+
```ruby
|
265
|
+
#controllers/users_controller.rb
|
266
|
+
#define a full_name column, allowing to create a custom search box that operates on the 4th column
|
267
|
+
define_columns :first_name, :last_name, :email, :full_name
|
268
|
+
define_column_order :last_name, :first_name, :email
|
269
|
+
```
|
270
|
+
#### define_column_offset
|
271
|
+
Sometimes you wish to manually add columns in the views before adding the defined TableSortable columns, eg. to have a checkbox next to each row.
|
272
|
+
```erb
|
273
|
+
<!-- views/users/index.html.erb -->
|
274
|
+
<table id="usersTable" data-query="<%= users_path %>">
|
275
|
+
<thead>
|
276
|
+
<tr></tr> <!-- EXTRA COLUMN -->
|
277
|
+
<tr>
|
278
|
+
<%= table_sortable_headers %>
|
279
|
+
</tr>
|
280
|
+
</thead>
|
281
|
+
<tbody>
|
282
|
+
</tbody>
|
283
|
+
</table>
|
284
|
+
|
285
|
+
<!-- views/users/_user_row.html.erb -->
|
286
|
+
<tr> <%= check_box_tag :checked %> </tr> <!-- EXTRA COLUMN -->
|
287
|
+
<tr>
|
288
|
+
<%= table_sortable_columns user %>
|
289
|
+
</tr>
|
290
|
+
```
|
291
|
+
Since the column numbers that appear in tableSorter.js' ajax request will represent their actual number, you should let TableSortable know that the columns you defined are offset.
|
292
|
+
So, in the above case you should define an offset of 1.
|
293
|
+
|
294
|
+
##### Syntax: `define_column_offset offset`
|
295
|
+
```ruby
|
296
|
+
define_column_offset 1
|
297
|
+
```
|
298
|
+
You may define it either using the `define_column_offset` method shown above,
|
299
|
+
or using the all inclusive `define_columns` method, as an `offset: <integer>` argument.
|
300
|
+
```ruby
|
301
|
+
define_column :first_name, :last_name, :email, offset: 1
|
302
|
+
```
|
142
303
|
|
143
304
|
### View Helpers
|
144
|
-
|
305
|
+
TableSortable offers several view helpers, to help maintain the connection between the view layer and the controller layer, and make your code DRYer and less error prone.
|
306
|
+
- [table_sortable_headers](#table_sortable_headers)
|
307
|
+
- [table_sortable_columns](#table_sortable_columns)
|
308
|
+
- [table_sortable_pager](#table_sortable_pager)
|
309
|
+
|
310
|
+
#### table_sortable_headers
|
311
|
+
##### Syntax: `table_sortable_headers [html_attributes]`
|
312
|
+
Renders the table header columns, each one inside a \<th> tag.
|
313
|
+
Notice that it _does not_ wrap a \<tr> tag around the headers, allowing you to add columns before of after TableSortable's headers.
|
314
|
+
|
315
|
+
It also renders data attributes that let tableSorter.js know the columns behaviour:
|
316
|
+
- `data-filter="false"` if the column's `filter` attribute is set to `false`.
|
317
|
+
- `data-sorter="false"` if the column's `sort` attribute is set to `false`.
|
318
|
+
- `data-placeholder="?"` if a placeholder has been defined (defaults to be the same as the column's label).
|
319
|
+
- `data-value="?"` if an initial filter value has been defined.
|
320
|
+
|
321
|
+
You may also specify any html attribute, as well as additional data attributes to be added to each \<th> element.
|
322
|
+
```erb
|
323
|
+
<tr> <%= table_sortable_headers class: 'text-center' %> </tr>
|
324
|
+
```
|
325
|
+
|
326
|
+
If you wish to render your own version of a specific header (eg. to add an icon),
|
327
|
+
you may create a partial inside a `table_sortable` folder nested inside the controller's views folder. The partial should be named according to the following naming scheme:
|
328
|
+
`_<template>_header.html`, with `template` corresponding to the column's template attribute.
|
329
|
+
Notice that in this case you need to manually specify the different data attributes that correspond to the behaviour you wish this column to have.
|
330
|
+
|
331
|
+
The view will be supplied with two locals:
|
332
|
+
- `label`: the column's label
|
333
|
+
- `column`: the TableSortable::Column object
|
334
|
+
|
335
|
+
Here is an example of a full name header partial, which includes a font-awesome icon:
|
336
|
+
```erb
|
337
|
+
<!-- views/users/table_sortable/_full_name_header.html.erb -->
|
338
|
+
<th data-placeholder="<%= column.placeholder %>">
|
339
|
+
<i class="fa fa-user" aria-hidden="true"></i>
|
340
|
+
<%= label %>
|
341
|
+
</th>
|
342
|
+
```
|
343
|
+
|
344
|
+
By using the template attribute you may render several columns using the same template.
|
345
|
+
|
346
|
+
_Notice that whether using slim or erb, you must include .html before the extension._
|
347
|
+
|
348
|
+
#### table_sortable_columns
|
349
|
+
##### Syntax: `table_sortable_columns record, [html_attributes]`
|
350
|
+
Renders the table columns for a specific `record`, each one inside a \<td> tag.
|
351
|
+
Notice that it _does not_ wrap a \<tr> tag around the headers, allowing you to add columns before of after TableSortable's columns.
|
352
|
+
|
353
|
+
It also renders data attributes that let tableSorter.js know the columns behaviour:
|
354
|
+
- `data-text="?"` if the column's `value` attribute is different than the column's `content` attribute, the value will be set in the `data-text` attribute, and the content will be displayed inside the \<td> element.
|
355
|
+
|
356
|
+
You may also specify any html attribute, as well as additional data attributes to be added to each \<td> element.
|
357
|
+
```erb
|
358
|
+
<tr> <%= table_sortable_columns @user, class: 'text-info' %> </tr>
|
359
|
+
```
|
360
|
+
|
361
|
+
If you wish to render your own version of a specific column (eg. to include a link inside of it),
|
362
|
+
you may create a partial inside a `table_sortable` folder nested inside the controller's views folder. The partial should be named according to the following naming scheme:
|
363
|
+
`_<template>_column.html`, with `template` corresponding to the column's template attribute.
|
364
|
+
Notice that in this case you need to manually specify the different data attributes that correspond to the behaviour you wish this column to have.
|
365
|
+
|
366
|
+
The view will be supplied with four locals:
|
367
|
+
- `source`: the source ActiveRecord object
|
368
|
+
- `content`: the column's content to be displayed
|
369
|
+
- `value`: the column's value
|
370
|
+
- `column`: the TableSortable::Column object
|
371
|
+
|
372
|
+
Here is an example of a full name column partial, in which the name links to the edit_user_path:
|
373
|
+
```erb
|
374
|
+
<!-- views/users/table_sortable/_full_name_column.html.erb -->
|
375
|
+
<td>
|
376
|
+
<%= link_to content, edit_user_path(source) %>
|
377
|
+
</td>
|
378
|
+
```
|
379
|
+
By using the template attribute you may render several columns using the same template.
|
380
|
+
|
381
|
+
_Notice that whether using slim, haml or erb, you must include .html before the extension._
|
382
|
+
|
383
|
+
#### table_sortable_pager
|
384
|
+
documentation coming soon...
|
145
385
|
|
146
386
|
## Development
|
147
387
|
|
@@ -3,18 +3,20 @@ module TableSortable
|
|
3
3
|
class Filter
|
4
4
|
include TableSortable::Concerns::Proc
|
5
5
|
|
6
|
-
attr_accessor :query
|
6
|
+
attr_accessor :query, :default_value
|
7
7
|
|
8
8
|
def initialize(*args)
|
9
|
-
|
9
|
+
options = args.extract_options!
|
10
|
+
@default_value = options[:filter_initial_value]
|
11
|
+
super :filter, options
|
10
12
|
end
|
11
13
|
|
12
14
|
def array_proc
|
13
|
-
-> (value, col=nil) { select{|record|
|
15
|
+
-> (value, col=nil) { select{|record| col.value(record).to_s.downcase.include? value.downcase} }
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
17
|
-
-> (value, col=nil) { where("LOWER(
|
18
|
+
def active_record_proc
|
19
|
+
-> (value, col=nil) { where("LOWER(#{col.name.to_s.underscore}) LIKE (?)", "%#{value.to_s.downcase}%") }
|
18
20
|
end
|
19
21
|
|
20
22
|
def proc_wrapper(proc)
|
@@ -13,8 +13,8 @@ module TableSortable
|
|
13
13
|
-> (sort_order, col=nil) { sort{ |a,b| col.value(sort_order == :asc ? a : b) <=> col.value(sort_order == :asc ? b : a) } }
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
-> (sort_order, col=nil) { order(
|
16
|
+
def active_record_proc
|
17
|
+
-> (sort_order, col=nil) { order(col.name.to_s.underscore => sort_order) }
|
18
18
|
end
|
19
19
|
|
20
20
|
def proc_wrapper(proc)
|
@@ -1,20 +1,27 @@
|
|
1
1
|
module TableSortable
|
2
2
|
class Column
|
3
3
|
|
4
|
-
attr_reader :name, :label, :filter, :sorter, :template, :placeholder
|
4
|
+
attr_reader :name, :label, :filter, :sorter, :template, :placeholder, :content#, :sort_priority
|
5
5
|
|
6
6
|
def initialize(col_name, *options)
|
7
7
|
|
8
8
|
options = options.extract_options!
|
9
9
|
value = options[:value] || col_name
|
10
|
+
content = options[:content] || value
|
10
11
|
label = options[:label] || (options[:label] == false ? '' : col_name.to_s.titleize)
|
11
|
-
placeholder = options[:placeholder] || (options[:placeholder] == false ?
|
12
|
+
placeholder = options[:placeholder] || (options[:placeholder] == false ? nil : label)
|
13
|
+
# priority = options[:priority]
|
12
14
|
template = options[:template] || col_name
|
13
15
|
|
16
|
+
# filter_defaultAttrib (data-value)
|
17
|
+
# data-sorter (=false?)
|
18
|
+
|
14
19
|
@name = col_name
|
15
|
-
@value = value.
|
20
|
+
@value = value.respond_to?(:call) ? value : -> (record) { record.send(value) }
|
21
|
+
@content = content.respond_to?(:call) ? content : -> (record) { record.send(content) }
|
16
22
|
@label = label
|
17
23
|
@placeholder = placeholder
|
24
|
+
# @sort_priority = sort_priority
|
18
25
|
@template = template
|
19
26
|
@filter = TableSortable::Column::Filter.new(options.merge(:column => self) )
|
20
27
|
@sorter = TableSortable::Column::Sorter.new(options.merge(:column => self) )
|
@@ -25,6 +32,10 @@ module TableSortable
|
|
25
32
|
record.instance_eval(&@value) unless @value.nil?
|
26
33
|
end
|
27
34
|
|
35
|
+
def content(record)
|
36
|
+
record.instance_eval(&@content) unless @content.nil?
|
37
|
+
end
|
38
|
+
|
28
39
|
end
|
29
40
|
|
30
41
|
end
|
@@ -4,7 +4,7 @@ module TableSortable
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
attr_reader :proc, :
|
7
|
+
attr_reader :proc, :column, :type
|
8
8
|
end
|
9
9
|
|
10
10
|
def initialize(option_name, *options)
|
@@ -12,8 +12,8 @@ module TableSortable
|
|
12
12
|
unless options[option_name] == false
|
13
13
|
@type = option_name
|
14
14
|
@column = options[:column]
|
15
|
-
the_proc = options[option_name] || @column.name
|
16
|
-
@method = options["#{option_name.to_s}_method".to_sym] || :
|
15
|
+
the_proc = options[option_name] || @column.name
|
16
|
+
@method = options["#{option_name.to_s}_method".to_sym] || :autodetect
|
17
17
|
if the_proc.respond_to? :call
|
18
18
|
@proc = proc_wrapper(the_proc)
|
19
19
|
@method = detect_method(@proc)
|
@@ -21,19 +21,35 @@ module TableSortable
|
|
21
21
|
case @method
|
22
22
|
when :array
|
23
23
|
@proc = array_proc
|
24
|
-
when :
|
25
|
-
@proc =
|
24
|
+
when :active_record
|
25
|
+
@proc = active_record_proc
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
def detect_method(proc)
|
31
|
+
def detect_method(proc, scope = nil)
|
32
32
|
begin
|
33
33
|
[].instance_exec('', &proc)
|
34
34
|
method = :array
|
35
35
|
rescue NoMethodError
|
36
|
-
method = :
|
36
|
+
method = :active_record
|
37
|
+
end
|
38
|
+
method
|
39
|
+
end
|
40
|
+
|
41
|
+
def method(record = nil)
|
42
|
+
return @method if record.nil?
|
43
|
+
if @method == :autodetect
|
44
|
+
if record.class.columns.map{|col| col.name.to_sym}.include? @column.name
|
45
|
+
method = :active_record
|
46
|
+
@proc = active_record_proc
|
47
|
+
else
|
48
|
+
method = :array
|
49
|
+
@proc = array_proc
|
50
|
+
end
|
51
|
+
else
|
52
|
+
method = @method
|
37
53
|
end
|
38
54
|
method
|
39
55
|
end
|
@@ -46,7 +62,7 @@ module TableSortable
|
|
46
62
|
raise NotImplementedError
|
47
63
|
end
|
48
64
|
|
49
|
-
def
|
65
|
+
def active_record_proc
|
50
66
|
raise NotImplementedError
|
51
67
|
end
|
52
68
|
|
@@ -18,7 +18,7 @@ module TableSortable
|
|
18
18
|
columns.each do |column|
|
19
19
|
define_column column
|
20
20
|
end
|
21
|
-
|
21
|
+
define_column_offset column_offset
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -27,6 +27,18 @@ module TableSortable
|
|
27
27
|
define_column *args
|
28
28
|
end
|
29
29
|
end
|
30
|
+
|
31
|
+
def define_column_order(order)
|
32
|
+
before_action do
|
33
|
+
define_column_order order
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def define_column_offset(offset)
|
38
|
+
before_action do
|
39
|
+
define_column_offset offset
|
40
|
+
end
|
41
|
+
end
|
30
42
|
end
|
31
43
|
|
32
44
|
def define_column(col_name, *options)
|
@@ -34,14 +46,26 @@ module TableSortable
|
|
34
46
|
@columns.add(col_name, options)
|
35
47
|
end
|
36
48
|
|
49
|
+
def define_column_order(*order)
|
50
|
+
@column_order = order
|
51
|
+
end
|
52
|
+
|
53
|
+
def define_column_offset(offset)
|
54
|
+
@column_offset = offset
|
55
|
+
end
|
56
|
+
|
57
|
+
def columns
|
58
|
+
@columns.sort_by(column_order)
|
59
|
+
end
|
60
|
+
|
37
61
|
private
|
38
62
|
|
39
63
|
def filter_and_sort(scope, params = nil)
|
40
64
|
populate_params(params)
|
41
65
|
|
42
66
|
actions = [->(records) { records }]
|
43
|
-
ordered_actions.reverse.each_with_index do |action, i|
|
44
|
-
actions << ->(records) { action.used? ? actions[i].call(action.run(records)) : actions[i].call(records) }
|
67
|
+
ordered_actions(scope.first).reverse.each_with_index do |action, i|
|
68
|
+
actions << ->(records) { action.used? ? (actions[i].call(action.run(records))) : actions[i].call(records) }
|
45
69
|
end
|
46
70
|
scope = actions.last.call(scope)
|
47
71
|
if @query_params.page
|
@@ -53,17 +77,13 @@ module TableSortable
|
|
53
77
|
|
54
78
|
def initialize_table_sortable
|
55
79
|
@columns = TableSortable::Columns.new
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
def columns
|
60
|
-
@columns.sort_by(display_order)
|
80
|
+
define_column_offset 0
|
61
81
|
end
|
62
82
|
|
63
|
-
def ordered_actions
|
83
|
+
def ordered_actions(record = nil)
|
64
84
|
filter_actions = @columns.map{|col| col.filter }
|
65
85
|
sort_actions = @columns.map{|col| col.sorter }
|
66
|
-
(filter_actions+sort_actions).sort{ |a,b| (a.method && b.method) ? (
|
86
|
+
(filter_actions+sort_actions).sort{ |a,b| (a.method(record) && b.method(record)) ? (a.method(record) <=> b.method(record)) : b.method(record) ? 1 : -1 }
|
67
87
|
end
|
68
88
|
|
69
89
|
def populate_params(params = nil)
|
@@ -72,8 +92,7 @@ module TableSortable
|
|
72
92
|
|
73
93
|
public
|
74
94
|
|
75
|
-
|
76
|
-
attr_accessor :display_order, :column_offset
|
95
|
+
attr_reader :column_order, :column_offset
|
77
96
|
|
78
97
|
end
|
79
98
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module TableSortable
|
2
|
+
module ViewHelpers
|
3
|
+
|
4
|
+
def table_sortable_pager(*args)
|
5
|
+
options = args.extract_options!
|
6
|
+
|
7
|
+
pagination_class = options[:wrapper_class] || 'pagination'
|
8
|
+
page_display_class = options[:page_display_class] || 'pagedisplay'
|
9
|
+
item_wrapper_class = options[:item_wrapper_class]
|
10
|
+
item_class = options[:item_class]
|
11
|
+
first_item = options[:first] || '<<'
|
12
|
+
prev_item = options[:prev] || '<'
|
13
|
+
next_item = options[:next] || '>'
|
14
|
+
last_item = options[:last] || '>>'
|
15
|
+
|
16
|
+
content_tag :ul, class:pagination_class do
|
17
|
+
content_tag(:li, link_to(first_item, '#', class: ([item_class] + ['first']).flatten.compact.join(' ')), class: item_wrapper_class)+
|
18
|
+
content_tag(:li, link_to(prev_item, '#', class: ([item_class] + ['prev'] ).flatten.compact.join(' ')), class: item_wrapper_class)+
|
19
|
+
content_tag(:li, content_tag(:span, nil, class: ([item_class] + [page_display_class]).flatten.compact.join(' ')), class: item_wrapper_class)+
|
20
|
+
content_tag(:li, link_to(next_item, '#', class: ([item_class] + ['next'] ).flatten.compact.join(' ')), class: item_wrapper_class)+
|
21
|
+
content_tag(:li, link_to(last_item, '#', class: ([item_class] + ['last'] ).flatten.compact.join(' ')), class: item_wrapper_class)
|
22
|
+
end.html_safe
|
23
|
+
end
|
24
|
+
|
25
|
+
def table_sortable_headers(html_options = {})
|
26
|
+
controller.columns.map do |col|
|
27
|
+
th_options = {}
|
28
|
+
th_options['data-placeholder'] = col.placeholder if col.placeholder
|
29
|
+
# th_options['data-priority'] = col.sort_priority if col.sort_priority
|
30
|
+
th_options['data-filter'] = 'false' if col.filter.disabled?
|
31
|
+
th_options['data-sorter'] = 'false' if col.sorter.disabled?
|
32
|
+
th_options['data-value'] = col.filter.default_value if col.filter.default_value
|
33
|
+
th_options.merge!(html_options)
|
34
|
+
|
35
|
+
begin
|
36
|
+
render partial: "#{controller_path}/table_sortable/#{col.template}_header.html",
|
37
|
+
locals: {label: col.label,
|
38
|
+
column: col}
|
39
|
+
rescue ActionView::MissingTemplate
|
40
|
+
content_tag :th, th_options do
|
41
|
+
col.label
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end.join.html_safe
|
45
|
+
end
|
46
|
+
|
47
|
+
def table_sortable_columns(record, html_options = {})
|
48
|
+
controller.columns.map do |col|
|
49
|
+
td_options = {}
|
50
|
+
td_options['data-text'] = col.value(record) if col.value(record) != col.content(record)
|
51
|
+
td_options.merge!(html_options)
|
52
|
+
|
53
|
+
begin
|
54
|
+
render partial: "#{controller_path}/table_sortable/#{col.template}_column.html",
|
55
|
+
locals: {content: col.content(record),
|
56
|
+
value: col.value(record),
|
57
|
+
source: record,
|
58
|
+
column: col}
|
59
|
+
rescue ActionView::MissingTemplate
|
60
|
+
content_tag :td, td_options do
|
61
|
+
col.value(record)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end.join.html_safe
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/table_sortable.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
require 'rails/engine'
|
2
1
|
require 'active_support/concern'
|
3
|
-
require 'action_controller'
|
4
2
|
|
5
3
|
module TableSortable
|
6
4
|
|
@@ -11,11 +9,10 @@ module TableSortable
|
|
11
9
|
PAGE = 'page'
|
12
10
|
PAGESIZE = 'pagesize'
|
13
11
|
|
14
|
-
class Engine < Rails::Engine; end
|
12
|
+
# class Engine < Rails::Engine; end
|
15
13
|
|
16
14
|
end
|
17
15
|
|
18
|
-
|
19
16
|
class TableSortableError < StandardError; end
|
20
17
|
|
21
18
|
require 'table_sortable/concerns/proc'
|
@@ -26,4 +23,5 @@ require 'table_sortable/result'
|
|
26
23
|
require 'table_sortable/columns'
|
27
24
|
require 'table_sortable/version'
|
28
25
|
require 'table_sortable/controller'
|
29
|
-
require 'table_sortable/query_params'
|
26
|
+
require 'table_sortable/query_params'
|
27
|
+
require 'table_sortable/railtie' if defined?(Rails)
|
@@ -1,14 +1,14 @@
|
|
1
1
|
shared_examples_for 'proc_class' do |parameter_name|
|
2
2
|
include_context 'shared stuff'
|
3
3
|
|
4
|
-
let(:dummy_class) { described_class.new(parameter_name => ->(x) {x}) }
|
4
|
+
let(:dummy_class) { described_class.new(parameter_name => ->(x) {x}, column: dummy_col) }
|
5
5
|
|
6
6
|
it 'includes TableSortable::Concerns::Proc' do
|
7
7
|
expect(described_class.included_modules).to include TableSortable::Concerns::Proc
|
8
8
|
end
|
9
9
|
it 'defines methods of its own' do
|
10
10
|
expect(dummy_class.array_proc).to respond_to :call
|
11
|
-
expect(dummy_class.
|
11
|
+
expect(dummy_class.active_record_proc).to respond_to :call
|
12
12
|
expect(dummy_class.send(:proc_wrapper, -> {x})).to respond_to :call
|
13
13
|
expect(dummy_class).to respond_to :run
|
14
14
|
expect(dummy_class).to respond_to :used?
|
@@ -9,7 +9,7 @@ describe TableSortable::Concerns::Proc do
|
|
9
9
|
-> (x) {x * 2}
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def active_record_proc
|
13
13
|
-> (x) {x * 3}
|
14
14
|
end
|
15
15
|
|
@@ -33,34 +33,29 @@ describe TableSortable::Concerns::Proc do
|
|
33
33
|
context 'it is an sql proc' do
|
34
34
|
it 'should detect it as sql' do
|
35
35
|
proc = proc_class.new(:proc, column: TableSortable::Column.new(:proc), proc: -> (value) { where(name: value) } )
|
36
|
-
expect(proc.method).to eq :
|
36
|
+
expect(proc.method).to eq :active_record
|
37
37
|
end
|
38
38
|
end
|
39
39
|
context 'it is an array proc' do
|
40
40
|
it 'should detect it as array' do
|
41
|
-
proc = proc_class.new(:proc, proc: -> (value) { select{|record| record.name == value} } )
|
41
|
+
proc = proc_class.new(:proc, column: dummy_col, proc: -> (value) { select{|record| record.name == value} } )
|
42
42
|
expect(proc.method).to eq :array
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
46
|
context 'given no proc' do
|
47
|
-
it 'should
|
48
|
-
expect(dummy_proc.method).to eq :
|
47
|
+
it 'should set method to autodetect' do
|
48
|
+
expect(dummy_proc.method).to eq :autodetect
|
49
49
|
end
|
50
50
|
context '_method: option' do
|
51
|
-
context '
|
52
|
-
it 'should replace it with
|
53
|
-
|
54
|
-
|
55
|
-
end
|
56
|
-
context '== :sql' do
|
57
|
-
it 'should replace it with sql_proc' do
|
58
|
-
dummy_proc = proc_class.new(:proc, column: TableSortable::Column.new(:proc), proc_method: :sql)
|
59
|
-
expect(5.instance_eval(&dummy_proc.proc)).to eq 5.instance_eval(&dummy_proc.sql_proc)
|
51
|
+
context '== :active_record' do
|
52
|
+
it 'should replace it with active_record_proc' do
|
53
|
+
dummy_proc = proc_class.new(:proc, column: TableSortable::Column.new(:proc), proc_method: :active_record)
|
54
|
+
expect(5.instance_eval(&dummy_proc.proc)).to eq 5.instance_eval(&dummy_proc.active_record_proc)
|
60
55
|
end
|
61
56
|
end
|
62
57
|
context '== :array' do
|
63
|
-
it 'should replace it with
|
58
|
+
it 'should replace it with active_record_proc' do
|
64
59
|
dummy_proc = proc_class.new(:proc, column: TableSortable::Column.new(:proc), proc_method: :array)
|
65
60
|
expect(5.instance_eval(&dummy_proc.proc)).to eq 5.instance_eval(&dummy_proc.array_proc)
|
66
61
|
end
|
@@ -73,7 +68,7 @@ describe TableSortable::Concerns::Proc do
|
|
73
68
|
context 'given a proc containing an sql method' do
|
74
69
|
it 'should detect it as sql' do
|
75
70
|
proc_to_detect = -> (filter_value) { where(name: filter_value) }
|
76
|
-
expect(dummy_proc.detect_method(proc_to_detect)).to eq :
|
71
|
+
expect(dummy_proc.detect_method(proc_to_detect)).to eq :active_record
|
77
72
|
end
|
78
73
|
end
|
79
74
|
context 'given a proc containing an array method' do
|
@@ -6,23 +6,22 @@ describe TableSortable::Controller do
|
|
6
6
|
controller.instance_eval('initialize_table_sortable')
|
7
7
|
controller
|
8
8
|
end
|
9
|
-
let :controller_with_columns do
|
10
9
|
|
10
|
+
let :controller_with_columns do
|
11
11
|
controller.send(:define_column,
|
12
|
-
:first_name
|
13
|
-
filter: -> (value) { where('UPPER(first_name) LIKE (?)', "%#{value.upcase}%") },
|
14
|
-
sort: -> (sort_order) { order(:first_name => sort_order) })
|
15
|
-
|
12
|
+
:first_name)#,
|
13
|
+
# filter: -> (value) { where('UPPER(first_name) LIKE (?)', "%#{value.upcase}%") },
|
14
|
+
# sort: -> (sort_order) { order(:first_name => sort_order) })
|
16
15
|
controller.send(:define_column,
|
17
16
|
:last_name,
|
18
|
-
filter: -> (value) { select{|record|
|
17
|
+
filter: -> (value) { select{|record| record.last_name.downcase.include? value.downcase }},
|
19
18
|
sort: -> (sort_order) { sort{ |a,b| (sort_order == :asc ? a : b).last_name <=> (sort_order == :asc ? b : a).last_name }})
|
20
|
-
|
19
|
+
controller.send(:define_column,
|
20
|
+
:full_name)
|
21
21
|
controller.send(:define_column,
|
22
22
|
:email,
|
23
23
|
filter: -> (value) { where('UPPER(email) LIKE (?)', "%#{value.upcase}%") },
|
24
24
|
sort: -> (sort_order) { order(:email => sort_order) })
|
25
|
-
|
26
25
|
controller
|
27
26
|
end
|
28
27
|
|
@@ -50,7 +49,7 @@ describe TableSortable::Controller do
|
|
50
49
|
|
51
50
|
context 'ordered_actions' do
|
52
51
|
it 'orders sql actions before array filters' do
|
53
|
-
expect(controller_with_columns.send(:ordered_actions).map{|action| action.method}).to eq [:
|
52
|
+
expect(controller_with_columns.send(:ordered_actions).map{|action| action.method}).to eq [:active_record, :active_record, :array, :array, :autodetect, :autodetect, :autodetect, :autodetect]
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
@@ -67,7 +66,7 @@ describe TableSortable::Controller do
|
|
67
66
|
sort_by_first_name = controller_with_columns.send(:filter_and_sort, User.all, {TableSortable::PAGESIZE => '10', TableSortable::PAGE => '0', TableSortable::SCOL => {'0' => TableSortable::SORT_ASC}})
|
68
67
|
expect(sort_by_first_name.pluck(:first_name)).to eq %w(Aaron Bob David Jim)
|
69
68
|
|
70
|
-
sort_by_email = controller_with_columns.send(:filter_and_sort, User.all, {TableSortable::PAGESIZE => '10', TableSortable::PAGE => '0', TableSortable::SCOL => {'
|
69
|
+
sort_by_email = controller_with_columns.send(:filter_and_sort, User.all, {TableSortable::PAGESIZE => '10', TableSortable::PAGE => '0', TableSortable::SCOL => {'3' => TableSortable::SORT_ASC}})
|
71
70
|
expect(sort_by_email.pluck(:first_name)).to eq %w(Jim David Bob Aaron)
|
72
71
|
end
|
73
72
|
context "sort order parameter equals #{TableSortable::SORT_DESC}" do
|
@@ -76,6 +75,8 @@ describe TableSortable::Controller do
|
|
76
75
|
expect(sort_by_last_name_desc.pluck(:first_name)).to eq %w(Aaron Jim Bob David)
|
77
76
|
end
|
78
77
|
end
|
78
|
+
it 'detects whether to use an active_record or array filter' do
|
79
79
|
|
80
|
+
end
|
80
81
|
end
|
81
82
|
end
|
data/spec/support/models/user.rb
CHANGED
data/table_sortable.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["davidovoded@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = 'Use jquery-tablesorter.js with server side filtering, pagination and sorting'
|
13
|
-
spec.description =
|
13
|
+
spec.description = "TableSortable adds multi-column, server-side filtering, sorting and pagination to the tableSorter jQuery plugin, so you don't have to worry about interpreting the query parameters, combining multiple queries, columns to sort by, or figuring out how to send the correct page back to the client. It is a Rails backend complementation to the frontend tableSorter.js."
|
14
14
|
spec.homepage = 'https://github.com/odedd/table_sortable'
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -34,5 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_development_dependency "rspec", "~> 3.4"
|
35
35
|
spec.add_development_dependency "sqlite3", "~> 1.3"
|
36
36
|
spec.add_development_dependency "factory_girl_rails", "~> 4.8"
|
37
|
-
spec.
|
37
|
+
spec.add_development_dependency "activerecord", '~> 5.1', '>= 5.1.1'
|
38
|
+
spec.add_dependency "railties", '~> 5.1', '>= 5.1.1'
|
39
|
+
# spec.add_dependency "activesupport", '~> 5.1', '>= 5.1.1'
|
38
40
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: table_sortable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oded Davidov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -81,7 +81,27 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '4.8'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: activerecord
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '5.1'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 5.1.1
|
93
|
+
type: :development
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '5.1'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 5.1.1
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: railties
|
85
105
|
requirement: !ruby/object:Gem::Requirement
|
86
106
|
requirements:
|
87
107
|
- - "~>"
|
@@ -100,8 +120,11 @@ dependencies:
|
|
100
120
|
- - ">="
|
101
121
|
- !ruby/object:Gem::Version
|
102
122
|
version: 5.1.1
|
103
|
-
description:
|
104
|
-
|
123
|
+
description: TableSortable adds multi-column, server-side filtering, sorting and pagination
|
124
|
+
to the tableSorter jQuery plugin, so you don't have to worry about interpreting
|
125
|
+
the query parameters, combining multiple queries, columns to sort by, or figuring
|
126
|
+
out how to send the correct page back to the client. It is a Rails backend complementation
|
127
|
+
to the frontend tableSorter.js.
|
105
128
|
email:
|
106
129
|
- davidovoded@gmail.com
|
107
130
|
executables: []
|
@@ -123,12 +146,6 @@ files:
|
|
123
146
|
- LICENSE.txt
|
124
147
|
- README.md
|
125
148
|
- Rakefile
|
126
|
-
- app/helpers/table_sortable_helper.rb
|
127
|
-
- app/views/table_sortable/_columns.slim
|
128
|
-
- app/views/table_sortable/_field.slim
|
129
|
-
- app/views/table_sortable/_header.slim
|
130
|
-
- app/views/table_sortable/_headers.slim
|
131
|
-
- app/views/table_sortable/_pager.slim
|
132
149
|
- bin/console
|
133
150
|
- bin/setup
|
134
151
|
- lib/table_sortable.rb
|
@@ -140,8 +157,10 @@ files:
|
|
140
157
|
- lib/table_sortable/controller.rb
|
141
158
|
- lib/table_sortable/process.rb
|
142
159
|
- lib/table_sortable/query_params.rb
|
160
|
+
- lib/table_sortable/railtie.rb
|
143
161
|
- lib/table_sortable/result.rb
|
144
162
|
- lib/table_sortable/version.rb
|
163
|
+
- lib/table_sortable/view_helpers.rb
|
145
164
|
- spec/concerns/proc_class_spec.rb
|
146
165
|
- spec/controllers/test_controller_spec.rb
|
147
166
|
- spec/lib/table_sortable/column/filter_spec.rb
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module TableSortableHelper
|
2
|
-
|
3
|
-
def table_sortable_pager
|
4
|
-
render 'table_sortable/pager'
|
5
|
-
end
|
6
|
-
|
7
|
-
def table_sortable_headers
|
8
|
-
render 'table_sortable/headers'
|
9
|
-
end
|
10
|
-
|
11
|
-
def table_sortable_columns(record)
|
12
|
-
render 'table_sortable/columns', record: record
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
td = value
|
@@ -1,42 +0,0 @@
|
|
1
|
-
.nav aria-label="Table Navigation"
|
2
|
-
ul.pagination
|
3
|
-
li.page-item
|
4
|
-
a.page-link.first = fa_icon 'fast-backward'
|
5
|
-
li.page-item
|
6
|
-
a.page-link.prev = fa_icon 'step-backward'
|
7
|
-
li.page-item
|
8
|
-
span.page-link.pagedisplay
|
9
|
-
li.page-item
|
10
|
-
a.page-link.next = fa_icon 'step-forward'
|
11
|
-
li.page-item
|
12
|
-
a.page-link.last = fa_icon 'fast-forward'
|
13
|
-
|
14
|
-
|
15
|
-
/<nav aria-label="Page navigation example">
|
16
|
-
/ <ul class="pagination">
|
17
|
-
/ <li class="page-item">
|
18
|
-
/ <a class="page-link" href="#" aria-label="Previous">
|
19
|
-
/ <span aria-hidden="true">«</span>
|
20
|
-
/ <span class="sr-only">Previous</span>
|
21
|
-
/ </a>
|
22
|
-
/ </li>
|
23
|
-
/ <li class="page-item"><a class="page-link" href="#">1</a></li>
|
24
|
-
/ <li class="page-item"><a class="page-link" href="#">2</a></li>
|
25
|
-
/ <li class="page-item"><a class="page-link" href="#">3</a></li>
|
26
|
-
/ <li class="page-item">
|
27
|
-
/ <a class="page-link" href="#" aria-label="Next">
|
28
|
-
/ <span aria-hidden="true">»</span>
|
29
|
-
/ <span class="sr-only">Next</span>
|
30
|
-
/ </a>
|
31
|
-
/ </li>
|
32
|
-
/ </ul>
|
33
|
-
/</nav>
|
34
|
-
|
35
|
-
/.row
|
36
|
-
/ .col.text-right
|
37
|
-
/ .pagination.my-0.justify-content-center
|
38
|
-
/ a.first.ml-1 = fa_icon 'fast-backward'
|
39
|
-
/ a.prev = fa_icon 'step-backward'
|
40
|
-
/ span.mx-1.pagedisplay
|
41
|
-
/ a.ml-1.next = fa_icon 'step-forward'
|
42
|
-
/ a.last = fa_icon 'fast-forward'
|