collate 0.1.3 → 0.1.4
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/README.md +127 -4
- data/lib/app/views/collate/_sort_select.html.haml +9 -0
- data/lib/collate/action_view_extension.rb +8 -0
- data/lib/collate/active_record_extension.rb +45 -1
- data/lib/collate/sorter.rb +23 -0
- data/lib/collate/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c576c73f42f7ce0da453c0e0e0778a69fd9a27f7
|
4
|
+
data.tar.gz: 9db7728b9973c4bd4575b6a00f733d0312d69ed6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64eb3c1bd01e5ffc31403424f1e3646bdb9e95a0fbb508bed7a1a3bca5a34e9e3f249cf39cb224565ebcb9e796c000d5a63a608210baf12631d4b40870b1f52b
|
7
|
+
data.tar.gz: 63b34d8658c421d24a87b125d818c9dd50c2bfb2285cfed011442cc4c486e01fcd712325215c874659644fd0ad2b071d16a81666cdb7444afacf00a11916b4b8
|
data/README.md
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
[](https://circleci.com/gh/trackingboard/collate)
|
4
4
|
[](https://coveralls.io/github/trackingboard/collate?branch=master)
|
5
|
-
[]()
|
6
|
-
[]()
|
5
|
+
[](https://rubygems.org/gems/collate)
|
6
|
+
[](https://rubygems.org/gems/collate)
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
@@ -13,11 +13,11 @@ or with bundler in your Gemfile:
|
|
13
13
|
|
14
14
|
```gem 'collate'```
|
15
15
|
|
16
|
-
## Usage
|
16
|
+
## Filter Usage
|
17
17
|
|
18
18
|
This gem currently only supports PostgreSQL.
|
19
19
|
|
20
|
-
To use collate in a model, include several collation definitions. The first argument is the name of the database column to use in the query. The simplest example looks like this:
|
20
|
+
To use collate filtering in a model, include several collation definitions. The first argument is the name of the database column to use in the query. The simplest example looks like this:
|
21
21
|
|
22
22
|
```
|
23
23
|
class Person < ActiveRecord::Base
|
@@ -284,6 +284,129 @@ In order to use this in a view, you could have some HAML like this:
|
|
284
284
|
|
285
285
|
This will ensure that the keys that the inputs are submitted with match the parameter key that the gem is expecting for that specific filter.
|
286
286
|
|
287
|
+
## Sorting Usage
|
288
|
+
|
289
|
+
To use collate sorting for a model, include several ```collate_sort``` defintions. For example:
|
290
|
+
|
291
|
+
```
|
292
|
+
class Person < ActiveRecord::Base
|
293
|
+
collate_sort :name
|
294
|
+
collate_sort :popularity
|
295
|
+
end
|
296
|
+
```
|
297
|
+
|
298
|
+
Then, in the controller, use the ```collate``` method:
|
299
|
+
|
300
|
+
```
|
301
|
+
@people = Person.collate(params)
|
302
|
+
```
|
303
|
+
|
304
|
+
This will cause the people to be sorted on either ```name``` or ```popularity``` if the ```params[:order]``` value is set appropriately.
|
305
|
+
|
306
|
+
```params[:order]``` must have a value of the format ```"#{table_name}.#{field_name} ASC``` or ```"#{table_name}.#{field_name} DESC```
|
307
|
+
|
308
|
+
For example:
|
309
|
+
|
310
|
+
```
|
311
|
+
params[:order] = "people.name ASC"
|
312
|
+
@people = Person.collate(params)
|
313
|
+
```
|
314
|
+
|
315
|
+
Will result in the following PostgreSQL query:
|
316
|
+
|
317
|
+
```
|
318
|
+
SELECT * FROM people ORDER BY people.name ASC
|
319
|
+
```
|
320
|
+
|
321
|
+
You can also pass parameter options to ```collate_sort``` for more complex sorting.
|
322
|
+
|
323
|
+
#### Default
|
324
|
+
--------------
|
325
|
+
```
|
326
|
+
collate_sort :name, default: 'asc'
|
327
|
+
```
|
328
|
+
|
329
|
+
This tells collate that this particular sorting should be performed if there is no other sorting specified by the user.
|
330
|
+
|
331
|
+
It is also the second sorting to be applied on top of another sort.
|
332
|
+
|
333
|
+
For instance:
|
334
|
+
|
335
|
+
```
|
336
|
+
class Person < ActiveRecord::Base
|
337
|
+
collate_sort :name, default: 'desc'
|
338
|
+
collate_sort :popularity
|
339
|
+
end
|
340
|
+
```
|
341
|
+
|
342
|
+
```
|
343
|
+
params[:order] = 'people.popularity ASC'
|
344
|
+
@people = Person.collate(params)
|
345
|
+
```
|
346
|
+
|
347
|
+
This would result in the following PostgreSQL query:
|
348
|
+
|
349
|
+
```
|
350
|
+
ORDER BY people.popularity ASC, people.name DESC
|
351
|
+
```
|
352
|
+
|
353
|
+
#### Joins
|
354
|
+
--------------
|
355
|
+
```
|
356
|
+
collate_sort 'posts.created_at', joins: [:posts]
|
357
|
+
```
|
358
|
+
|
359
|
+
This will perform the ActiveRecord joins before the sorting is applied. Doing this will allow you to sort on fields that are on related models.
|
360
|
+
|
361
|
+
#### Field_select
|
362
|
+
--------------
|
363
|
+
```
|
364
|
+
collate_sort 'post_count', joins: [:posts], field_select: 'COUNT(posts.*) as post_count'
|
365
|
+
```
|
366
|
+
|
367
|
+
This will perform the ActiveRecord select before the sorting is applied. Doing this will allow you to sort on fields created using a subquery.
|
368
|
+
|
369
|
+
#### Nulls_first
|
370
|
+
--------------
|
371
|
+
```
|
372
|
+
collate_sort :popularity, nulls_first: true
|
373
|
+
```
|
374
|
+
|
375
|
+
This will append ```NULLS FIRST``` to the order portion of the database query
|
376
|
+
|
377
|
+
#### Nulls_last
|
378
|
+
--------------
|
379
|
+
```
|
380
|
+
collate_sort :popularity, nulls_last: true
|
381
|
+
```
|
382
|
+
|
383
|
+
This will append ```NULLS LAST``` to the order portion of the database query
|
384
|
+
|
385
|
+
#### Label
|
386
|
+
--------------
|
387
|
+
```
|
388
|
+
collate_sort :popularity, label: 'Popularity Score'
|
389
|
+
```
|
390
|
+
|
391
|
+
This will modify the default sorting label, which is ```field.to_s.titleize```.
|
392
|
+
|
393
|
+
#### Asc_label
|
394
|
+
--------------
|
395
|
+
```
|
396
|
+
collate_sort :popularity, asc_label: 'Popularity Score Lowest to Highest'
|
397
|
+
```
|
398
|
+
|
399
|
+
This will modify the default ascending sorting label, which is ```#{label} ⬇```.
|
400
|
+
|
401
|
+
#### Desc_label
|
402
|
+
--------------
|
403
|
+
```
|
404
|
+
collate_sort :popularity, desc_label: 'Popularity Score Highest to Lowest'
|
405
|
+
```
|
406
|
+
|
407
|
+
This will modify the default descending sorting label, which is ```#{label} ⬆```.
|
408
|
+
|
409
|
+
|
287
410
|
## Contributing
|
288
411
|
|
289
412
|
Bug reports and pull requests are welcome on GitHub at https://github.com/trackingboard/collate.
|
@@ -0,0 +1,9 @@
|
|
1
|
+
%select.collate_sort{opts}
|
2
|
+
- if opts[:allow_none]
|
3
|
+
%option{value: "", selected: (params[:order].to_s == "")}
|
4
|
+
None
|
5
|
+
- sorters.each do |sorter|
|
6
|
+
%option{value: "#{sorter.field} ASC", selected: (params[:order] == "#{sorter.field} ASC")}
|
7
|
+
= sorter.asc_label
|
8
|
+
%option{value: "#{sorter.field} DESC", selected: (params[:order] == "#{sorter.field} DESC")}
|
9
|
+
= sorter.desc_label
|
@@ -10,6 +10,14 @@ module Collate
|
|
10
10
|
filters
|
11
11
|
end
|
12
12
|
|
13
|
+
def sorting_for record, opts={}
|
14
|
+
sorters = record.model.collate_sorters ||= []
|
15
|
+
|
16
|
+
opts[:name] ||= "order"
|
17
|
+
|
18
|
+
render :partial => "collate/sort_select", locals: {sorters: sorters, opts: opts}
|
19
|
+
end
|
20
|
+
|
13
21
|
def filter_for filter
|
14
22
|
render :partial => "collate/#{filter.component[:type]}_field", locals: {filter: filter}
|
15
23
|
end
|
@@ -1,8 +1,15 @@
|
|
1
1
|
require_relative 'filter'
|
2
|
+
require_relative 'sorter'
|
2
3
|
|
3
4
|
module Collate
|
4
5
|
module ActiveRecordExtension
|
5
6
|
|
7
|
+
def collate_sort field, opts={}
|
8
|
+
initialize_collate
|
9
|
+
|
10
|
+
self.collate_sorters << Collate::Sorter.new(field, opts.merge({base_model_table_name: self.table_name}))
|
11
|
+
end
|
12
|
+
|
6
13
|
def collate_on field, opts={}
|
7
14
|
initialize_collate
|
8
15
|
|
@@ -33,6 +40,20 @@ module Collate
|
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
43
|
+
self.collate_sorters.each do |sorter|
|
44
|
+
sort_field, _, sort_direction = params[:order].to_s.partition(' ')
|
45
|
+
|
46
|
+
if(sort_field == sorter.field && ['ASC','DESC'].include?(sort_direction))
|
47
|
+
ar_rel = apply_sorter ar_rel, sorter, params[:order]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
default_sort = self.collate_sorters.select { |s| s.default }.first
|
52
|
+
if default_sort.present?
|
53
|
+
ar_rel = apply_sorter ar_rel, default_sort, "#{default_sort.field} #{default_sort.default.upcase}", 'order'
|
54
|
+
params[:order] = "#{default_sort.field} #{default_sort.default.upcase}"
|
55
|
+
end
|
56
|
+
|
36
57
|
ar_rel
|
37
58
|
end
|
38
59
|
|
@@ -41,14 +62,37 @@ module Collate
|
|
41
62
|
def initialize_collate
|
42
63
|
if !self.method_defined? :collate_filters
|
43
64
|
class << self
|
44
|
-
attr_accessor :collate_filters, :default_group, :group_options
|
65
|
+
attr_accessor :collate_filters, :collate_sorters, :default_group, :group_options
|
45
66
|
end
|
46
67
|
end
|
47
68
|
self.collate_filters ||= {}
|
69
|
+
self.collate_sorters ||= []
|
48
70
|
self.default_group ||= :main
|
49
71
|
self.group_options ||= {}
|
50
72
|
end
|
51
73
|
|
74
|
+
def apply_sorter ar_rel, sorter, param_value, sorting_method = 'reorder'
|
75
|
+
if sorter.joins
|
76
|
+
sorter.joins.each do |join|
|
77
|
+
ar_rel = ar_rel.joins(join)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
ar_rel = ar_rel.select("#{ar_rel.table_name}.*")
|
82
|
+
|
83
|
+
sorter.field_select = sorter.field unless sorter.field_select
|
84
|
+
|
85
|
+
ar_rel = ar_rel.select(sorter.field_select)
|
86
|
+
|
87
|
+
ar_rel = if sorter.nulls_first
|
88
|
+
ar_rel.send(sorting_method, "#{param_value} NULLS FIRST")
|
89
|
+
elsif sorter.nulls_last
|
90
|
+
ar_rel.send(sorting_method, "#{param_value} NULLS LAST")
|
91
|
+
else
|
92
|
+
ar_rel.send(sorting_method, param_value)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
52
96
|
def apply_filter ar_rel, filter, param_value
|
53
97
|
filter_value = if param_value.duplicable?
|
54
98
|
param_value.dup
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Collate
|
2
|
+
class Sorter
|
3
|
+
attr_accessor :field, :base_model_table_name, :label, :asc_label, :desc_label,
|
4
|
+
:field_select, :joins, :default, :nulls_last, :nulls_first
|
5
|
+
|
6
|
+
def initialize(field, opt={})
|
7
|
+
opt.each do |field, value|
|
8
|
+
self.send("#{field}=", value)
|
9
|
+
end
|
10
|
+
|
11
|
+
self.field = field
|
12
|
+
|
13
|
+
self.label ||= self.field.to_s.titleize
|
14
|
+
self.asc_label ||= "#{label} ⬇"
|
15
|
+
self.desc_label ||= "#{label} ⬆"
|
16
|
+
|
17
|
+
self.field = "#{base_model_table_name}.#{field}" if field.is_a? Symbol
|
18
|
+
|
19
|
+
self.joins ||= []
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/collate/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: collate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicholas Page
|
@@ -176,12 +176,14 @@ files:
|
|
176
176
|
- lib/app/views/collate/_checkboxgroup_field.html.haml
|
177
177
|
- lib/app/views/collate/_date_field.html.haml
|
178
178
|
- lib/app/views/collate/_select_field.html.haml
|
179
|
+
- lib/app/views/collate/_sort_select.html.haml
|
179
180
|
- lib/app/views/collate/_string_field.html.haml
|
180
181
|
- lib/collate.rb
|
181
182
|
- lib/collate/action_view_extension.rb
|
182
183
|
- lib/collate/active_record_extension.rb
|
183
184
|
- lib/collate/engine.rb
|
184
185
|
- lib/collate/filter.rb
|
186
|
+
- lib/collate/sorter.rb
|
185
187
|
- lib/collate/version.rb
|
186
188
|
homepage: https://github.com/trackingboard/collate
|
187
189
|
licenses:
|