miscellany 0.1.18 → 0.1.19
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/lib/miscellany/controller/sliced_response.rb +1 -1
- data/lib/miscellany/sort_lang.rb +31 -17
- data/lib/miscellany/version.rb +1 -1
- data/spec/miscellany/sort_lang_spec.rb +124 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e919c60e03780d5fab1a21ae6d528482db21d5a4fcfbc176b4808cc1d9acdc77
|
|
4
|
+
data.tar.gz: c9ecbbbb69e28e8fbef7aa9efe93db1cab9576634ede5ad2dc698180c1743dda
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7468e0d150c79e5ebfb5760648e97699c7b88340c68b7eaa530c58e512ee982eb1d2b44c2599b374a7348a5b9cefe7d7037603a98aa5a8a895f18bac6d4efe84
|
|
7
|
+
data.tar.gz: 0a7dfb9250e3f686d88f7c2932cbd1a8b07f0a38ae4d3e491e98ee4c14a22126bcf3defd58227130fe3a43f8cd7d0b5dbaf002f6ded24fd187706b445fcce28e
|
data/lib/miscellany/sort_lang.rb
CHANGED
|
@@ -23,6 +23,21 @@ module Miscellany
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def self.sqlize(sorts)
|
|
26
|
+
seen_sorts = Set.new
|
|
27
|
+
|
|
28
|
+
# Only include each sort key/"column" once
|
|
29
|
+
sorts = sorts.select do |sort|
|
|
30
|
+
sid = sort[:key] || sort[:column]
|
|
31
|
+
next true unless sid.present?
|
|
32
|
+
|
|
33
|
+
if seen_sorts.include?(sid)
|
|
34
|
+
false
|
|
35
|
+
else
|
|
36
|
+
seen_sorts << sid
|
|
37
|
+
true
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
26
41
|
sorts.map do |sort|
|
|
27
42
|
order = sort[:order] || 'ASC'
|
|
28
43
|
if sort[:column].is_a?(Proc)
|
|
@@ -45,12 +60,20 @@ module Miscellany
|
|
|
45
60
|
class Parser
|
|
46
61
|
class SortParsingError < StandardError; end
|
|
47
62
|
|
|
63
|
+
attr_reader :default_sorts
|
|
64
|
+
|
|
48
65
|
def initialize(valid_sorts, default: nil)
|
|
49
|
-
@sorts_map = normalize_sort_options(valid_sorts
|
|
50
|
-
|
|
66
|
+
@sorts_map = normalize_sort_options(valid_sorts)
|
|
67
|
+
|
|
68
|
+
@default_sorts = []
|
|
51
69
|
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
parsed_defaults = normalize_sort_options(Array(default))
|
|
71
|
+
parsed_defaults.each do |k,v|
|
|
72
|
+
@sorts_map[k] ||= v
|
|
73
|
+
end
|
|
74
|
+
@default_sorts = parsed_defaults.keys.map do |k|
|
|
75
|
+
@sorts_map[k]
|
|
76
|
+
end
|
|
54
77
|
end
|
|
55
78
|
|
|
56
79
|
def valid?(sortstr)
|
|
@@ -80,14 +103,16 @@ module Miscellany
|
|
|
80
103
|
sort
|
|
81
104
|
end
|
|
82
105
|
|
|
83
|
-
|
|
106
|
+
if default == :append || default && !sorts.compact.present?
|
|
107
|
+
sorts.push(*self.default_sorts)
|
|
108
|
+
end
|
|
84
109
|
|
|
85
110
|
sorts.compact.presence
|
|
86
111
|
end
|
|
87
112
|
|
|
88
113
|
protected
|
|
89
114
|
|
|
90
|
-
def normalize_sort_options(sorts
|
|
115
|
+
def normalize_sort_options(sorts)
|
|
91
116
|
norm_sorts = { }
|
|
92
117
|
|
|
93
118
|
sorts.each do |s|
|
|
@@ -100,20 +125,9 @@ module Miscellany
|
|
|
100
125
|
else
|
|
101
126
|
sort_hash = normalize_sort(s)
|
|
102
127
|
norm_sorts[sort_hash[:column]] = sort_hash
|
|
103
|
-
# default ||= sort_hash
|
|
104
128
|
end
|
|
105
129
|
end
|
|
106
130
|
|
|
107
|
-
if default.present?
|
|
108
|
-
norm_default = normalize_sort(default)
|
|
109
|
-
reference = norm_sorts[norm_default[:key].to_s] || norm_default
|
|
110
|
-
norm_sorts[:default] = {
|
|
111
|
-
key: reference[:key],
|
|
112
|
-
column: reference[:column],
|
|
113
|
-
order: norm_default[:order] || reference[:order],
|
|
114
|
-
}
|
|
115
|
-
end
|
|
116
|
-
|
|
117
131
|
norm_sorts
|
|
118
132
|
end
|
|
119
133
|
|
data/lib/miscellany/version.rb
CHANGED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
describe Miscellany::SortLang do
|
|
5
|
+
|
|
6
|
+
describe ".normalize_sort" do
|
|
7
|
+
it "accepts Hash KV pairs" do
|
|
8
|
+
expect(Miscellany::SortLang.normalize_sort(["key", { column: "created_at", order: "ASC" }])).to eql({
|
|
9
|
+
column: "created_at", force_order: false, key: "created_at", order: "ASC"
|
|
10
|
+
})
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "accepts strings" do
|
|
14
|
+
expect(Miscellany::SortLang.normalize_sort("created_at")).to eql({
|
|
15
|
+
column: "created_at", force_order: false, key: "created_at"
|
|
16
|
+
})
|
|
17
|
+
expect(Miscellany::SortLang.normalize_sort("created_at ASC")).to eql({
|
|
18
|
+
column: "created_at", force_order: false, key: "created_at", order: "ASC"
|
|
19
|
+
})
|
|
20
|
+
expect(Miscellany::SortLang.normalize_sort("created_at ASC!")).to eql({
|
|
21
|
+
column: "created_at", force_order: true, key: "created_at", order: "ASC"
|
|
22
|
+
})
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "accepts Procs" do
|
|
26
|
+
logic = ->(x) { "created_at #{x}" }
|
|
27
|
+
expect(Miscellany::SortLang.normalize_sort(logic, key: "k")).to eql({
|
|
28
|
+
column: logic, key: "k"
|
|
29
|
+
})
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe ".sqlize" do
|
|
34
|
+
it "only includes each sort key once" do
|
|
35
|
+
expect(Miscellany::SortLang.sqlize([
|
|
36
|
+
{ column: "created_at", order: "ASC" },
|
|
37
|
+
{ column: "created_at", order: "DESC" },
|
|
38
|
+
])).to eql "created_at ASC NULLS FIRST"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "nulls: option" do
|
|
42
|
+
it "accepts a nulls: option" do
|
|
43
|
+
expect(Miscellany::SortLang.sqlize([
|
|
44
|
+
{ column: "created_at", order: "ASC", nulls: :last },
|
|
45
|
+
])).to eql "created_at ASC NULLS LAST"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "nulls: :high works" do
|
|
49
|
+
expect(Miscellany::SortLang.sqlize([
|
|
50
|
+
{ column: "created_at", order: "ASC", nulls: :high },
|
|
51
|
+
])).to eql "created_at ASC NULLS LAST"
|
|
52
|
+
expect(Miscellany::SortLang.sqlize([
|
|
53
|
+
{ column: "created_at", order: "DESC", nulls: :high },
|
|
54
|
+
])).to eql "created_at DESC NULLS FIRST"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "nulls: :low works" do
|
|
58
|
+
expect(Miscellany::SortLang.sqlize([
|
|
59
|
+
{ column: "created_at", order: "ASC", nulls: :low },
|
|
60
|
+
])).to eql "created_at ASC NULLS FIRST"
|
|
61
|
+
expect(Miscellany::SortLang.sqlize([
|
|
62
|
+
{ column: "created_at", order: "DESC", nulls: :low },
|
|
63
|
+
])).to eql "created_at DESC NULLS LAST"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe Miscellany::SortLang::Parser do
|
|
69
|
+
let(:valid_sorts) {[
|
|
70
|
+
"title", "created_at"
|
|
71
|
+
]}
|
|
72
|
+
let(:default_sort) { "title" }
|
|
73
|
+
|
|
74
|
+
let(:subject) { Miscellany::SortLang::Parser.new(valid_sorts, default: default_sort) }
|
|
75
|
+
|
|
76
|
+
context "with multiple default sorts" do
|
|
77
|
+
let(:default_sort) { ["title", "created_at"] }
|
|
78
|
+
|
|
79
|
+
it "includes each" do
|
|
80
|
+
expect(subject.parse(nil)).to eql [
|
|
81
|
+
{:column=>"title", :force_order=>false, :key=>"title"},
|
|
82
|
+
{:column=>"created_at", :force_order=>false, :key=>"created_at"},
|
|
83
|
+
]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe "#parse" do
|
|
88
|
+
it "excludes uknown sorts" do
|
|
89
|
+
expect(subject.parse("updated_at")).to eql [
|
|
90
|
+
{:column=>"title", :force_order=>false, :key=>"title"},
|
|
91
|
+
]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "considers force_order" do
|
|
95
|
+
subject = Miscellany::SortLang::Parser.new([ "title ASC!" ])
|
|
96
|
+
expect(subject.parse("title DESC")).to eql [
|
|
97
|
+
{:column=>"title", :force_order=>true, :key=>"title", :order=>"ASC"},
|
|
98
|
+
]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "returns the default sort if no sort is given" do
|
|
102
|
+
expect(subject.parse("")).to eql [
|
|
103
|
+
{:column=>"title", :force_order=>false, :key=>"title"},
|
|
104
|
+
]
|
|
105
|
+
expect(subject.parse("", default: true)).to eql [
|
|
106
|
+
{:column=>"title", :force_order=>false, :key=>"title"},
|
|
107
|
+
]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "appends the default sort" do
|
|
111
|
+
expect(subject.parse("created_at", default: :append)).to eql [
|
|
112
|
+
{:column=>"created_at", :force_order=>false, :key=>"created_at"},
|
|
113
|
+
{:column=>"title", :force_order=>false, :key=>"title"},
|
|
114
|
+
]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "excludes the default sort" do
|
|
118
|
+
expect(subject.parse("created_at", default: false)).to eql [
|
|
119
|
+
{:column=>"created_at", :force_order=>false, :key=>"created_at"},
|
|
120
|
+
]
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: miscellany
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.19
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ethan Knapp
|
|
@@ -149,6 +149,7 @@ files:
|
|
|
149
149
|
- spec/miscellany/goldiload_value_spec.rb
|
|
150
150
|
- spec/miscellany/param_validator_spec.rb
|
|
151
151
|
- spec/miscellany/sliced_response_spec.rb
|
|
152
|
+
- spec/miscellany/sort_lang_spec.rb
|
|
152
153
|
- spec/spec_helper.rb
|
|
153
154
|
homepage: https://instructure.com
|
|
154
155
|
licenses: []
|
|
@@ -174,6 +175,7 @@ specification_version: 4
|
|
|
174
175
|
summary: Gem for a bunch of random, re-usable Rails Concerns & Helpers
|
|
175
176
|
test_files:
|
|
176
177
|
- spec/db/database.yml
|
|
178
|
+
- spec/miscellany/sort_lang_spec.rb
|
|
177
179
|
- spec/miscellany/arbitrary_prefetch_spec.rb
|
|
178
180
|
- spec/miscellany/sliced_response_spec.rb
|
|
179
181
|
- spec/miscellany/param_validator_spec.rb
|