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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1dea6efd8728954e80a8a249f749dd8133ecfcf71fb6b4a3b3acf248b662fca8
4
- data.tar.gz: bd567ce813d303ca03d8d87f8faa4a312d2417b934bb1ee8c3d2781b99126f88
3
+ metadata.gz: e919c60e03780d5fab1a21ae6d528482db21d5a4fcfbc176b4808cc1d9acdc77
4
+ data.tar.gz: c9ecbbbb69e28e8fbef7aa9efe93db1cab9576634ede5ad2dc698180c1743dda
5
5
  SHA512:
6
- metadata.gz: 66f32e979d580c4297c1155f6bc87203ec808420856636724a257d07ca062ffe5d5ecd073aaa0fa0b09efb781f033affce87faa579b0007bd7f4ffe46c82fda3
7
- data.tar.gz: 54210f971ad74cd8d14b4934cb36d155943626b5e66190c682c294fdcd30f3b315cf2b5dbae268ce70a1213726e294978c80b080fdf8422bd1256a4f47dd3f37
6
+ metadata.gz: 7468e0d150c79e5ebfb5760648e97699c7b88340c68b7eaa530c58e512ee982eb1d2b44c2599b374a7348a5b9cefe7d7037603a98aa5a8a895f18bac6d4efe84
7
+ data.tar.gz: 0a7dfb9250e3f686d88f7c2932cbd1a8b07f0a38ae4d3e491e98ee4c14a22126bcf3defd58227130fe3a43f8cd7d0b5dbaf002f6ded24fd187706b445fcce28e
@@ -219,7 +219,7 @@ module Miscellany
219
219
 
220
220
  def sort_sql
221
221
  sorts = [ *Array(self.sort) ]
222
- sorts << options[:sort_parser]&.default
222
+ sorts.push(*options[:sort_parser]&.default_sorts)
223
223
  sorts.compact!
224
224
 
225
225
  return nil unless sorts.present?
@@ -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, default: default)
50
- end
66
+ @sorts_map = normalize_sort_options(valid_sorts)
67
+
68
+ @default_sorts = []
51
69
 
52
- def default
53
- @sorts_map[:default]
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
- sorts << self.default if default == :append || default && !sorts.compact.present?
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, default: nil)
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
 
@@ -1,3 +1,3 @@
1
1
  module Miscellany
2
- VERSION = "0.1.18".freeze
2
+ VERSION = "0.1.19".freeze
3
3
  end
@@ -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.18
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