collate 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![CircleCI](https://img.shields.io/circleci/project/github/trackingboard/collate.svg)](https://circleci.com/gh/trackingboard/collate)
|
4
4
|
[![Coveralls](https://img.shields.io/coveralls/trackingboard/collate.svg)](https://coveralls.io/github/trackingboard/collate?branch=master)
|
5
|
-
[![Gem](https://img.shields.io/gem/v/collate.svg)]()
|
6
|
-
[![Gem](https://img.shields.io/gem/dt/collate.svg)]()
|
5
|
+
[![Gem](https://img.shields.io/gem/v/collate.svg)](https://rubygems.org/gems/collate)
|
6
|
+
[![Gem](https://img.shields.io/gem/dt/collate.svg)](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:
|