miscellany 0.1.17 → 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
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
|
@@ -7,8 +7,8 @@ module Miscellany
|
|
7
7
|
include HttpErrorHandling
|
8
8
|
|
9
9
|
# Deprecated
|
10
|
-
def slice_results(
|
11
|
-
@sliced_data = sliced_json(
|
10
|
+
def slice_results(*args, **kwargs, &blk)
|
11
|
+
@sliced_data = sliced_json(*args, **kwargs, &blk)
|
12
12
|
end
|
13
13
|
|
14
14
|
def sliced_json(
|
@@ -219,7 +219,7 @@ module Miscellany
|
|
219
219
|
|
220
220
|
def sort_sql
|
221
221
|
sorts = [ *Array(self.sort) ]
|
222
|
-
sorts
|
222
|
+
sorts.push(*options[:sort_parser]&.default_sorts)
|
223
223
|
sorts.compact!
|
224
224
|
|
225
225
|
return nil unless sorts.present?
|
data/lib/miscellany/sort_lang.rb
CHANGED
@@ -23,10 +23,25 @@ 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)
|
29
|
-
sort[:column].call(
|
44
|
+
sort[:column].call(order)
|
30
45
|
else
|
31
46
|
desired_nulls = (sort[:nulls] || :low).to_s.downcase.to_sym
|
32
47
|
nulls = case desired_nulls
|
@@ -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,39 +103,31 @@ 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|
|
94
119
|
if s.is_a?(Hash)
|
95
120
|
s.each do |k,v|
|
121
|
+
k = k.to_s
|
96
122
|
sort_hash = normalize_sort(v, key: k)
|
97
123
|
norm_sorts[k] = sort_hash
|
98
124
|
end
|
99
125
|
else
|
100
126
|
sort_hash = normalize_sort(s)
|
101
127
|
norm_sorts[sort_hash[:column]] = sort_hash
|
102
|
-
# default ||= sort_hash
|
103
128
|
end
|
104
129
|
end
|
105
130
|
|
106
|
-
if default.present?
|
107
|
-
norm_default = normalize_sort(default)
|
108
|
-
reference = norm_sorts[norm_default[:key].to_s] || norm_default
|
109
|
-
norm_sorts[:default] = {
|
110
|
-
key: reference[:key],
|
111
|
-
column: reference[:column],
|
112
|
-
order: norm_default[:order] || reference[:order],
|
113
|
-
}
|
114
|
-
end
|
115
|
-
|
116
131
|
norm_sorts
|
117
132
|
end
|
118
133
|
|
data/lib/miscellany/version.rb
CHANGED
@@ -129,6 +129,19 @@ describe Miscellany::SlicedResponse do
|
|
129
129
|
|
130
130
|
expect(subject.sliced_json(ARModel.all, { page: "all" }, allow_all: true, **slice_config)).to be_a Hash
|
131
131
|
end
|
132
|
+
|
133
|
+
context "with Hash-based valid_sorts" do
|
134
|
+
let(:source) { ARModel.all }
|
135
|
+
|
136
|
+
before(:each) do
|
137
|
+
slice_config[:valid_sorts] = [
|
138
|
+
title: ->(dir) { "title #{dir}" }
|
139
|
+
]
|
140
|
+
end
|
141
|
+
|
142
|
+
include_examples "basic functionality"
|
143
|
+
include_examples "sortable"
|
144
|
+
end
|
132
145
|
end
|
133
146
|
|
134
147
|
describe "#bearcat_as_sliced_json" do
|
@@ -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,14 +1,14 @@
|
|
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
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -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
|