dbee 1.0.3 → 1.1.0
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/CHANGELOG.md +11 -0
- data/lib/dbee/key_chain.rb +1 -1
- data/lib/dbee/model/constraints/base.rb +5 -3
- data/lib/dbee/model.rb +11 -7
- data/lib/dbee/query/field.rb +3 -1
- data/lib/dbee/query/filters/base.rb +6 -3
- data/lib/dbee/query/sorters/ascending.rb +19 -0
- data/lib/dbee/query/sorters/base.rb +43 -0
- data/lib/dbee/query/sorters/descending.rb +19 -0
- data/lib/dbee/query/sorters.rb +29 -0
- data/lib/dbee/query.rb +15 -7
- data/lib/dbee/version.rb +1 -1
- data/spec/dbee/key_path_spec.rb +5 -0
- data/spec/dbee/model/constraints/base_spec.rb +9 -2
- data/spec/dbee/model/constraints/reference_spec.rb +9 -2
- data/spec/dbee/model/constraints/static_spec.rb +9 -1
- data/spec/dbee/model_spec.rb +11 -2
- data/spec/dbee/query/field_spec.rb +5 -0
- data/spec/dbee/query/filters/base_spec.rb +8 -2
- data/spec/dbee/query/sorters/ascending_spec.rb +41 -0
- data/spec/dbee/query/{sorter_spec.rb → sorters/base_spec.rb} +7 -32
- data/spec/dbee/query/sorters/descending_spec.rb +41 -0
- data/spec/dbee/query_spec.rb +65 -0
- metadata +12 -5
- data/lib/dbee/query/sorter.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01e542a4c7d9eb3f9641aa7b54f776f32b88e178129ad0e4af219b3965315090
|
4
|
+
data.tar.gz: a94879eb871f87ed9b9c3f7bccbe3ddfa5a177f558a842572f7632d09feab1fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af62cb3558f7557e939be6b5b4606c299436f782b40441bad3dac27c18560c9c9e55b1884c3645dcfada969f8d704c0aeb313e9731d0dd1cfcab8d7e634efa9e
|
7
|
+
data.tar.gz: 9f87776b0c84ff7c31c0df4d08d7f0725064adcdec21c8653995d1370426bd7d5a3b13c33946e8c1b72816cf0d9906ea0bc970ba61656876d84b3e0081fb93bc
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# 1.1.0 (August 28th, 2019)
|
2
|
+
|
3
|
+
Additions:
|
4
|
+
|
5
|
+
* Added better equality and sort methods for Ruby objects (added class type checks where needed.)
|
6
|
+
|
7
|
+
Changes:
|
8
|
+
|
9
|
+
* Removed Sorter in favor of Sorter subclasses.
|
10
|
+
* Duplicate filters and sorters will be ignored in a Query.
|
11
|
+
|
1
12
|
# 1.0.3 (August 27th, 2019)
|
2
13
|
|
3
14
|
Additions:
|
data/lib/dbee/key_chain.rb
CHANGED
@@ -22,15 +22,17 @@ module Dbee
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def <=>(other)
|
25
|
-
"#{name}#{parent}" <=> "#{other.name}#{other.parent}"
|
25
|
+
"#{self.class.name}#{name}#{parent}" <=> "#{other.class.name}#{other.name}#{other.parent}"
|
26
26
|
end
|
27
27
|
|
28
28
|
def hash
|
29
|
-
"#{name}#{parent}".hash
|
29
|
+
"#{self.class.name}#{name}#{parent}".hash
|
30
30
|
end
|
31
31
|
|
32
32
|
def ==(other)
|
33
|
-
other.
|
33
|
+
other.instance_of?(self.class) &&
|
34
|
+
other.name == name &&
|
35
|
+
other.parent == parent
|
34
36
|
end
|
35
37
|
alias eql? ==
|
36
38
|
end
|
data/lib/dbee/model.rb
CHANGED
@@ -13,6 +13,7 @@ module Dbee
|
|
13
13
|
# In DB terms, a Model is usually a table, but it does not have to be. You can also re-model
|
14
14
|
# your DB schema using Dbee::Models.
|
15
15
|
class Model
|
16
|
+
extend Forwardable
|
16
17
|
acts_as_hashable
|
17
18
|
|
18
19
|
JOIN_CHAR = '.'
|
@@ -23,6 +24,12 @@ module Dbee
|
|
23
24
|
|
24
25
|
attr_reader :constraints, :name, :table
|
25
26
|
|
27
|
+
def_delegator :models_by_name, :values, :models
|
28
|
+
|
29
|
+
def_delegator :models, :sort, :sorted_models
|
30
|
+
|
31
|
+
def_delegator :constraints, :sort, :sorted_constraints
|
32
|
+
|
26
33
|
def initialize(name:, constraints: [], models: [], table: '')
|
27
34
|
raise ArgumentError, 'name is required' if name.to_s.empty?
|
28
35
|
|
@@ -38,10 +45,6 @@ module Dbee
|
|
38
45
|
array.map { |a| [a.name, a] }.to_h
|
39
46
|
end
|
40
47
|
|
41
|
-
def models
|
42
|
-
models_by_name.values
|
43
|
-
end
|
44
|
-
|
45
48
|
def ancestors(parts = [], alias_chain = [], found = {})
|
46
49
|
return found if Array(parts).empty?
|
47
50
|
|
@@ -63,10 +66,11 @@ module Dbee
|
|
63
66
|
end
|
64
67
|
|
65
68
|
def ==(other)
|
66
|
-
other.
|
69
|
+
other.instance_of?(self.class) &&
|
70
|
+
other.name == name &&
|
67
71
|
other.table == table &&
|
68
|
-
other.
|
69
|
-
other.
|
72
|
+
other.sorted_constraints == sorted_constraints &&
|
73
|
+
other.sorted_models == sorted_models
|
70
74
|
end
|
71
75
|
alias eql? ==
|
72
76
|
|
data/lib/dbee/query/field.rb
CHANGED
@@ -26,16 +26,19 @@ module Dbee
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def hash
|
29
|
-
"#{key_path}#{value}".hash
|
29
|
+
"#{self.class.name}#{key_path}#{value}".hash
|
30
30
|
end
|
31
31
|
|
32
32
|
def ==(other)
|
33
|
-
other.
|
33
|
+
other.instance_of?(self.class) &&
|
34
|
+
other.key_path == key_path &&
|
35
|
+
other.value == value
|
34
36
|
end
|
35
37
|
alias eql? ==
|
36
38
|
|
37
39
|
def <=>(other)
|
38
|
-
"#{
|
40
|
+
"#{self.class.name}#{key_path}#{value}" <=>
|
41
|
+
"#{other.class.name}#{other.key_path}#{other.value}"
|
39
42
|
end
|
40
43
|
end
|
41
44
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'base'
|
11
|
+
|
12
|
+
module Dbee
|
13
|
+
class Query
|
14
|
+
class Sorters
|
15
|
+
# Equivalent to: ORDER BY field ASC
|
16
|
+
class Ascending < Base; end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Dbee
|
11
|
+
class Query
|
12
|
+
class Sorters
|
13
|
+
# Abstract representation of the ORDER BY part of a SQL statement.
|
14
|
+
class Base
|
15
|
+
acts_as_hashable
|
16
|
+
|
17
|
+
attr_reader :key_path
|
18
|
+
|
19
|
+
def initialize(key_path:)
|
20
|
+
raise ArgumentError, 'key_path is required' if key_path.to_s.empty?
|
21
|
+
|
22
|
+
@key_path = KeyPath.get(key_path)
|
23
|
+
|
24
|
+
freeze
|
25
|
+
end
|
26
|
+
|
27
|
+
def hash
|
28
|
+
"#{self.class.name}#{key_path}".hash
|
29
|
+
end
|
30
|
+
|
31
|
+
def ==(other)
|
32
|
+
other.instance_of?(self.class) &&
|
33
|
+
other.key_path == key_path
|
34
|
+
end
|
35
|
+
alias eql? ==
|
36
|
+
|
37
|
+
def <=>(other)
|
38
|
+
"#{key_path}#{self.class.name}" <=> "#{other.key_path}#{other.class.name}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'base'
|
11
|
+
|
12
|
+
module Dbee
|
13
|
+
class Query
|
14
|
+
class Sorters
|
15
|
+
# Equivalent to: ORDER BY field DESC
|
16
|
+
class Descending < Base; end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'sorters/ascending'
|
11
|
+
require_relative 'sorters/descending'
|
12
|
+
|
13
|
+
module Dbee
|
14
|
+
class Query
|
15
|
+
# Top-level class that allows for the making of sorters. For example, you can call this as:
|
16
|
+
# - Sorters.make(key_path: 'id', direction: :ascending)
|
17
|
+
# - Sorters.make(key_path: 'id')
|
18
|
+
# - Sorters.make(key_path: 'id', direction: :descending)
|
19
|
+
class Sorters
|
20
|
+
acts_as_hashable_factory
|
21
|
+
|
22
|
+
type_key 'direction'
|
23
|
+
|
24
|
+
register '', Ascending # Default if type is blank.
|
25
|
+
register 'ascending', Ascending
|
26
|
+
register 'descending', Descending
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/dbee/query.rb
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
|
10
10
|
require_relative 'query/field'
|
11
11
|
require_relative 'query/filters'
|
12
|
-
require_relative 'query/
|
12
|
+
require_relative 'query/sorters'
|
13
13
|
|
14
14
|
module Dbee
|
15
15
|
# This class is an abstration of a simplified SQL expression. In DB terms:
|
@@ -18,12 +18,19 @@ module Dbee
|
|
18
18
|
# - limit is the TAKE
|
19
19
|
# - filters are the WHERE
|
20
20
|
class Query
|
21
|
+
extend Forwardable
|
21
22
|
acts_as_hashable
|
22
23
|
|
23
24
|
class NoFieldsError < StandardError; end
|
24
25
|
|
25
26
|
attr_reader :fields, :filters, :limit, :sorters
|
26
27
|
|
28
|
+
def_delegator :fields, :sort, :sorted_fields
|
29
|
+
|
30
|
+
def_delegator :filters, :sort, :sorted_filters
|
31
|
+
|
32
|
+
def_delegator :sorters, :sort, :sorted_sorters
|
33
|
+
|
27
34
|
def initialize(fields:, filters: [], limit: nil, sorters: [])
|
28
35
|
@fields = Field.array(fields)
|
29
36
|
|
@@ -32,18 +39,19 @@ module Dbee
|
|
32
39
|
# have implications in downstream SQL generators.
|
33
40
|
raise NoFieldsError if @fields.empty?
|
34
41
|
|
35
|
-
@filters = Filters.array(filters)
|
42
|
+
@filters = Filters.array(filters).uniq
|
36
43
|
@limit = limit.to_s.empty? ? nil : limit.to_i
|
37
|
-
@sorters =
|
44
|
+
@sorters = Sorters.array(sorters).uniq
|
38
45
|
|
39
46
|
freeze
|
40
47
|
end
|
41
48
|
|
42
49
|
def ==(other)
|
43
|
-
other.
|
44
|
-
other.
|
45
|
-
other.
|
46
|
-
other.
|
50
|
+
other.instance_of?(self.class) &&
|
51
|
+
other.sorted_fields == sorted_fields &&
|
52
|
+
other.sorted_filters == sorted_filters &&
|
53
|
+
other.sorted_sorters == sorted_sorters &&
|
54
|
+
other.limit == limit
|
47
55
|
end
|
48
56
|
alias eql? ==
|
49
57
|
|
data/lib/dbee/version.rb
CHANGED
data/spec/dbee/key_path_spec.rb
CHANGED
@@ -33,6 +33,11 @@ describe Dbee::KeyPath do
|
|
33
33
|
expect(subject).to eql(key_path_string)
|
34
34
|
end
|
35
35
|
|
36
|
+
specify 'equality compares to_s of both objects' do
|
37
|
+
expect(subject).to eq(key_path_string)
|
38
|
+
expect(subject).to eql(:'contacts.demographics.first')
|
39
|
+
end
|
40
|
+
|
36
41
|
describe '#ancestor_paths' do
|
37
42
|
let(:key_path_string) { 'a.b.c.d.e' }
|
38
43
|
|
@@ -39,8 +39,10 @@ describe Dbee::Model::Constraints::Base do
|
|
39
39
|
|
40
40
|
subject { described_class.new(config) }
|
41
41
|
|
42
|
-
specify '#hash produces same output as string hash of name' do
|
43
|
-
|
42
|
+
specify '#hash produces same output as string hash of class name, name, and parent' do
|
43
|
+
expected_hash = "#{described_class.name}#{config[:name]}#{config[:parent]}".hash
|
44
|
+
|
45
|
+
expect(subject.hash).to eq(expected_hash)
|
44
46
|
end
|
45
47
|
|
46
48
|
specify '#== and #eql? compares attributes' do
|
@@ -49,5 +51,10 @@ describe Dbee::Model::Constraints::Base do
|
|
49
51
|
expect(subject).to eq(object2)
|
50
52
|
expect(subject).to eql(object2)
|
51
53
|
end
|
54
|
+
|
55
|
+
it 'returns false unless comparing same object types' do
|
56
|
+
expect(subject).not_to eq(config)
|
57
|
+
expect(subject).not_to eq(nil)
|
58
|
+
end
|
52
59
|
end
|
53
60
|
end
|
@@ -23,8 +23,10 @@ describe Dbee::Model::Constraints::Reference do
|
|
23
23
|
|
24
24
|
subject { described_class.new(config) }
|
25
25
|
|
26
|
-
specify '#hash produces same output as
|
27
|
-
|
26
|
+
specify '#hash produces same output as string hash of class name, name, and parent' do
|
27
|
+
expected_hash = "#{described_class.name}#{config[:name]}#{config[:parent]}".hash
|
28
|
+
|
29
|
+
expect(subject.hash).to eq(expected_hash)
|
28
30
|
end
|
29
31
|
|
30
32
|
specify '#== and #eql? compare attributes' do
|
@@ -33,5 +35,10 @@ describe Dbee::Model::Constraints::Reference do
|
|
33
35
|
expect(subject).to eq(object2)
|
34
36
|
expect(subject).to eql(object2)
|
35
37
|
end
|
38
|
+
|
39
|
+
it 'returns false unless comparing same object types' do
|
40
|
+
expect(subject).not_to eq(config)
|
41
|
+
expect(subject).not_to eq(nil)
|
42
|
+
end
|
36
43
|
end
|
37
44
|
end
|
@@ -24,7 +24,10 @@ describe Dbee::Model::Constraints::Static do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
specify '#hash produces same output as concatenated string hash of name and parent' do
|
27
|
-
|
27
|
+
parent_hash = "#{described_class.name}#{config[:name]}#{config[:parent]}".hash
|
28
|
+
expected_hash = "#{parent_hash}#{config[:value]}".hash
|
29
|
+
|
30
|
+
expect(subject.hash).to eq(expected_hash)
|
28
31
|
end
|
29
32
|
|
30
33
|
specify '#== and #eql? compare attributes' do
|
@@ -33,5 +36,10 @@ describe Dbee::Model::Constraints::Static do
|
|
33
36
|
expect(subject).to eq(object2)
|
34
37
|
expect(subject).to eql(object2)
|
35
38
|
end
|
39
|
+
|
40
|
+
it 'returns false unless comparing same object types' do
|
41
|
+
expect(subject).not_to eq(config)
|
42
|
+
expect(subject).not_to eq(nil)
|
43
|
+
end
|
36
44
|
end
|
37
45
|
end
|
data/spec/dbee/model_spec.rb
CHANGED
@@ -89,16 +89,25 @@ describe Dbee::Model do
|
|
89
89
|
|
90
90
|
expect(plan).to eq(expected_plan)
|
91
91
|
end
|
92
|
+
end
|
92
93
|
|
93
|
-
|
94
|
-
|
94
|
+
describe 'equality' do
|
95
|
+
let(:config) { yaml_fixture('models.yaml')['Theaters, Members, and Movies'] }
|
96
|
+
|
97
|
+
subject { described_class.make(config) }
|
95
98
|
|
99
|
+
specify 'equality compares attributes' do
|
96
100
|
model1 = described_class.make(config)
|
97
101
|
model2 = described_class.make(config)
|
98
102
|
|
99
103
|
expect(model1).to eq(model2)
|
100
104
|
expect(model1).to eql(model2)
|
101
105
|
end
|
106
|
+
|
107
|
+
it 'returns false unless comparing same object types' do
|
108
|
+
expect(subject).not_to eq(config)
|
109
|
+
expect(subject).not_to eq(nil)
|
110
|
+
end
|
102
111
|
end
|
103
112
|
|
104
113
|
context 'README examples' do
|
@@ -38,5 +38,10 @@ describe Dbee::Query::Field do
|
|
38
38
|
expect(subject).to eq(object2)
|
39
39
|
expect(subject).to eql(object2)
|
40
40
|
end
|
41
|
+
|
42
|
+
it 'returns false unless comparing same object types' do
|
43
|
+
expect(subject).not_to eq('a.b.c')
|
44
|
+
expect(subject).not_to eq(nil)
|
45
|
+
end
|
41
46
|
end
|
42
47
|
end
|
@@ -28,8 +28,9 @@ describe Dbee::Query::Filters::Base do
|
|
28
28
|
|
29
29
|
subject { described_class.new(config) }
|
30
30
|
|
31
|
-
specify '#hash produces same output as
|
32
|
-
|
31
|
+
specify '#hash produces same output as string hash of class name, key_path, and value' do
|
32
|
+
expected_hash = "#{described_class.name}#{config[:key_path]}#{config[:value]}".hash
|
33
|
+
expect(subject.hash).to eq(expected_hash)
|
33
34
|
end
|
34
35
|
|
35
36
|
specify '#== and #eql? compare attributes' do
|
@@ -38,5 +39,10 @@ describe Dbee::Query::Filters::Base do
|
|
38
39
|
expect(subject).to eq(object2)
|
39
40
|
expect(subject).to eql(object2)
|
40
41
|
end
|
42
|
+
|
43
|
+
it 'returns false unless comparing same object types' do
|
44
|
+
expect(subject).not_to eq('a.b.c')
|
45
|
+
expect(subject).not_to eq(nil)
|
46
|
+
end
|
41
47
|
end
|
42
48
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'spec_helper'
|
11
|
+
|
12
|
+
describe Dbee::Query::Sorters::Ascending do
|
13
|
+
context 'equality' do
|
14
|
+
let(:config) do
|
15
|
+
{ key_path: 'a.b.c' }
|
16
|
+
end
|
17
|
+
|
18
|
+
subject { described_class.new(config) }
|
19
|
+
|
20
|
+
it 'returns true if instance class and key_paths are equal' do
|
21
|
+
subject2 = described_class.new(config)
|
22
|
+
|
23
|
+
expect(subject).to eq(subject2)
|
24
|
+
expect(subject).to eql(subject2)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns false if instance class is different' do
|
28
|
+
subject2 = Dbee::Query::Sorters::Descending.new(config)
|
29
|
+
|
30
|
+
expect(subject).not_to eq(subject2)
|
31
|
+
expect(subject).not_to eql(subject2)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns false if key_path is different' do
|
35
|
+
subject2 = described_class.new(key_path: 'd.e.f')
|
36
|
+
|
37
|
+
expect(subject).not_to eq(subject2)
|
38
|
+
expect(subject).not_to eql(subject2)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -9,7 +9,7 @@
|
|
9
9
|
|
10
10
|
require 'spec_helper'
|
11
11
|
|
12
|
-
describe Dbee::Query::
|
12
|
+
describe Dbee::Query::Sorters::Base do
|
13
13
|
it 'should act as hashable' do
|
14
14
|
expect(described_class).to respond_to(:make)
|
15
15
|
expect(described_class).to respond_to(:array)
|
@@ -24,12 +24,12 @@ describe Dbee::Query::Sorter do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
context 'equality' do
|
27
|
-
let(:config) { { key_path: 'a.b.c'
|
27
|
+
let(:config) { { key_path: 'a.b.c' } }
|
28
28
|
|
29
29
|
subject { described_class.new(config) }
|
30
30
|
|
31
|
-
specify '#hash produces same output as concatenated string hash of
|
32
|
-
expect(subject.hash).to eq("#{
|
31
|
+
specify '#hash produces same output as concatenated string hash of class name and key_path' do
|
32
|
+
expect(subject.hash).to eq("#{described_class.name}#{config[:key_path]}".hash)
|
33
33
|
end
|
34
34
|
|
35
35
|
specify '#== and #eql? compare attributes' do
|
@@ -38,35 +38,10 @@ describe Dbee::Query::Sorter do
|
|
38
38
|
expect(subject).to eq(object2)
|
39
39
|
expect(subject).to eql(object2)
|
40
40
|
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe 'direction helpers' do
|
44
|
-
context 'when direction is ascending' do
|
45
|
-
let(:config) { { key_path: 'a.b.c' } }
|
46
|
-
|
47
|
-
subject { described_class.new(config) }
|
48
|
-
|
49
|
-
it '#ascending? is true' do
|
50
|
-
expect(subject.ascending?).to be true
|
51
|
-
end
|
52
|
-
|
53
|
-
it '#descending? is false' do
|
54
|
-
expect(subject.descending?).to be false
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context 'when direction is descending' do
|
59
|
-
let(:config) { { key_path: 'a.b.c', direction: :descending } }
|
60
|
-
|
61
|
-
subject { described_class.new(config) }
|
62
|
-
|
63
|
-
it '#ascending? is false' do
|
64
|
-
expect(subject.ascending?).to be false
|
65
|
-
end
|
66
41
|
|
67
|
-
|
68
|
-
|
69
|
-
|
42
|
+
it 'returns false unless comparing same object types' do
|
43
|
+
expect(subject).not_to eq('a.b.c')
|
44
|
+
expect(subject).not_to eq(nil)
|
70
45
|
end
|
71
46
|
end
|
72
47
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'spec_helper'
|
11
|
+
|
12
|
+
describe Dbee::Query::Sorters::Descending do
|
13
|
+
context 'equality' do
|
14
|
+
let(:config) do
|
15
|
+
{ key_path: 'a.b.c' }
|
16
|
+
end
|
17
|
+
|
18
|
+
subject { described_class.new(config) }
|
19
|
+
|
20
|
+
it 'returns true if instance class and key_paths are equal' do
|
21
|
+
subject2 = described_class.new(config)
|
22
|
+
|
23
|
+
expect(subject).to eq(subject2)
|
24
|
+
expect(subject).to eql(subject2)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns false if instance class is different' do
|
28
|
+
subject2 = Dbee::Query::Sorters::Ascending.new(config)
|
29
|
+
|
30
|
+
expect(subject).not_to eq(subject2)
|
31
|
+
expect(subject).not_to eql(subject2)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns false if key_path is different' do
|
35
|
+
subject2 = described_class.new(key_path: 'd.e.f')
|
36
|
+
|
37
|
+
expect(subject).not_to eq(subject2)
|
38
|
+
expect(subject).not_to eql(subject2)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/spec/dbee/query_spec.rb
CHANGED
@@ -43,6 +43,71 @@ describe Dbee::Query do
|
|
43
43
|
it 'should raise a NoFieldsError if no fields were passed in' do
|
44
44
|
expect { described_class.new(fields: []) }.to raise_error(Dbee::Query::NoFieldsError)
|
45
45
|
end
|
46
|
+
|
47
|
+
it 'should remove duplicate filters (keep first instance)' do
|
48
|
+
query_hash = {
|
49
|
+
fields: [
|
50
|
+
{ key_path: 'a' }
|
51
|
+
],
|
52
|
+
filters: [
|
53
|
+
{ key_path: 'a', value: 'something' },
|
54
|
+
{ key_path: 'b', value: 123 },
|
55
|
+
{ key_path: 'b', value: '123' },
|
56
|
+
{ key_path: 'c', value: nil },
|
57
|
+
{ key_path: 'c', value: '' },
|
58
|
+
{ key_path: 'd', value: 'r', type: :greater_than_or_equal_to },
|
59
|
+
{ key_path: 'd', value: 'r' },
|
60
|
+
{ key_path: 'e', value: [1, 2, 3] },
|
61
|
+
{ key_path: 'a', value: 'something' },
|
62
|
+
{ key_path: 'e', value: [1, 2, 3] }
|
63
|
+
]
|
64
|
+
}
|
65
|
+
|
66
|
+
expected_filters = Dbee::Query::Filters.array(
|
67
|
+
[
|
68
|
+
{ key_path: 'a', value: 'something' },
|
69
|
+
{ key_path: 'b', value: 123 },
|
70
|
+
{ key_path: 'b', value: '123' },
|
71
|
+
{ key_path: 'c', value: nil },
|
72
|
+
{ key_path: 'c', value: '' },
|
73
|
+
{
|
74
|
+
key_path: 'd',
|
75
|
+
value: 'r',
|
76
|
+
type: :greater_than_or_equal_to
|
77
|
+
},
|
78
|
+
{ key_path: 'd', value: 'r' },
|
79
|
+
{ key_path: 'e', value: [1, 2, 3] }
|
80
|
+
]
|
81
|
+
)
|
82
|
+
|
83
|
+
expect(described_class.make(query_hash).filters).to eq(expected_filters)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should remove duplicate sorters (keep first instance)' do
|
87
|
+
query_hash = {
|
88
|
+
fields: [
|
89
|
+
{ key_path: 'a' }
|
90
|
+
],
|
91
|
+
sorters: [
|
92
|
+
{ key_path: 'a' },
|
93
|
+
{ key_path: 'b' },
|
94
|
+
{ key_path: 'c', direction: :descending },
|
95
|
+
{ key_path: '1' },
|
96
|
+
{ key_path: :a },
|
97
|
+
{ key_path: 1 },
|
98
|
+
{ key_path: 'c', direction: :descending }
|
99
|
+
]
|
100
|
+
}
|
101
|
+
|
102
|
+
expected_sorters = Dbee::Query::Sorters.array([
|
103
|
+
{ key_path: 'a' },
|
104
|
+
{ key_path: 'b' },
|
105
|
+
{ key_path: 'c', direction: :descending },
|
106
|
+
{ key_path: '1' }
|
107
|
+
])
|
108
|
+
|
109
|
+
expect(described_class.make(query_hash).sorters).to eq(expected_sorters)
|
110
|
+
end
|
46
111
|
end
|
47
112
|
|
48
113
|
describe '#key_chain' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acts_as_hashable
|
@@ -178,7 +178,10 @@ files:
|
|
178
178
|
- lib/dbee/query/filters/not_equals.rb
|
179
179
|
- lib/dbee/query/filters/not_start_with.rb
|
180
180
|
- lib/dbee/query/filters/starts_with.rb
|
181
|
-
- lib/dbee/query/
|
181
|
+
- lib/dbee/query/sorters.rb
|
182
|
+
- lib/dbee/query/sorters/ascending.rb
|
183
|
+
- lib/dbee/query/sorters/base.rb
|
184
|
+
- lib/dbee/query/sorters/descending.rb
|
182
185
|
- lib/dbee/version.rb
|
183
186
|
- spec/dbee/base_spec.rb
|
184
187
|
- spec/dbee/key_chain_spec.rb
|
@@ -192,7 +195,9 @@ files:
|
|
192
195
|
- spec/dbee/query/field_spec.rb
|
193
196
|
- spec/dbee/query/filters/base_spec.rb
|
194
197
|
- spec/dbee/query/filters_spec.rb
|
195
|
-
- spec/dbee/query/
|
198
|
+
- spec/dbee/query/sorters/ascending_spec.rb
|
199
|
+
- spec/dbee/query/sorters/base_spec.rb
|
200
|
+
- spec/dbee/query/sorters/descending_spec.rb
|
196
201
|
- spec/dbee/query_spec.rb
|
197
202
|
- spec/dbee_spec.rb
|
198
203
|
- spec/fixtures/models.rb
|
@@ -234,7 +239,9 @@ test_files:
|
|
234
239
|
- spec/dbee/query/field_spec.rb
|
235
240
|
- spec/dbee/query/filters/base_spec.rb
|
236
241
|
- spec/dbee/query/filters_spec.rb
|
237
|
-
- spec/dbee/query/
|
242
|
+
- spec/dbee/query/sorters/ascending_spec.rb
|
243
|
+
- spec/dbee/query/sorters/base_spec.rb
|
244
|
+
- spec/dbee/query/sorters/descending_spec.rb
|
238
245
|
- spec/dbee/query_spec.rb
|
239
246
|
- spec/dbee_spec.rb
|
240
247
|
- spec/fixtures/models.rb
|
data/lib/dbee/query/sorter.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
#
|
4
|
-
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
-
#
|
6
|
-
# This source code is licensed under the MIT license found in the
|
7
|
-
# LICENSE file in the root directory of this source tree.
|
8
|
-
#
|
9
|
-
|
10
|
-
module Dbee
|
11
|
-
class Query
|
12
|
-
# Abstract representation of the ORDER BY part of a SQL statement.
|
13
|
-
class Sorter
|
14
|
-
acts_as_hashable
|
15
|
-
|
16
|
-
module Direction
|
17
|
-
ASCENDING = :ascending
|
18
|
-
DESCENDING = :descending
|
19
|
-
end
|
20
|
-
include Direction
|
21
|
-
|
22
|
-
attr_reader :direction, :key_path
|
23
|
-
|
24
|
-
def initialize(key_path:, direction: ASCENDING)
|
25
|
-
raise ArgumentError, 'key_path is required' if key_path.to_s.empty?
|
26
|
-
|
27
|
-
@direction = Direction.const_get(direction.to_s.upcase.to_sym)
|
28
|
-
@key_path = KeyPath.get(key_path)
|
29
|
-
|
30
|
-
freeze
|
31
|
-
end
|
32
|
-
|
33
|
-
def descending?
|
34
|
-
direction == DESCENDING
|
35
|
-
end
|
36
|
-
|
37
|
-
def ascending?
|
38
|
-
!descending?
|
39
|
-
end
|
40
|
-
|
41
|
-
def hash
|
42
|
-
"#{key_path}#{direction}".hash
|
43
|
-
end
|
44
|
-
|
45
|
-
def ==(other)
|
46
|
-
other.key_path == key_path && other.direction == direction
|
47
|
-
end
|
48
|
-
alias eql? ==
|
49
|
-
|
50
|
-
def <=>(other)
|
51
|
-
"#{key_path}#{direction}" <=> "#{other.key_path}#{other.direction}"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|