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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aac48262d54b0524c4c8ecbe241ec9896478f7b02917376b835b64a75f6401bb
4
- data.tar.gz: 94285e874df6c27cabd1c212b3456ce77351ee91c34c58bbfc430c1c8183667f
3
+ metadata.gz: 01e542a4c7d9eb3f9641aa7b54f776f32b88e178129ad0e4af219b3965315090
4
+ data.tar.gz: a94879eb871f87ed9b9c3f7bccbe3ddfa5a177f558a842572f7632d09feab1fc
5
5
  SHA512:
6
- metadata.gz: 893af6c116b4687dd80bd4f25c96c991950bdfb799f3de590a33a9780c86ba287f4767c96ea8c6c1f10766c410a9be52fe29194c22ea29d30c9474c59acd4eff
7
- data.tar.gz: 5863a68e275638f4b1d34c4326ed3b19b5ef433abed897e8f2bcbf5ec7eb536f5b54c8f666c1e339e49059bbc3ff2a6771b03db8cef6596bd76328b0ebe204e8
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:
@@ -29,7 +29,7 @@ module Dbee
29
29
  end
30
30
 
31
31
  def ==(other)
32
- key_path_set == other.key_path_set
32
+ other.instance_of?(self.class) && key_path_set == other.key_path_set
33
33
  end
34
34
  alias eql? ==
35
35
 
@@ -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.name == name && other.parent == parent
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.name == name &&
69
+ other.instance_of?(self.class) &&
70
+ other.name == name &&
67
71
  other.table == table &&
68
- other.models.sort == models.sort &&
69
- other.constraints.sort == constraints.sort
72
+ other.sorted_constraints == sorted_constraints &&
73
+ other.sorted_models == sorted_models
70
74
  end
71
75
  alias eql? ==
72
76
 
@@ -31,7 +31,9 @@ module Dbee
31
31
  end
32
32
 
33
33
  def ==(other)
34
- other.key_path == key_path && other.display == display
34
+ other.instance_of?(self.class) &&
35
+ other.key_path == key_path &&
36
+ other.display == display
35
37
  end
36
38
  alias eql? ==
37
39
 
@@ -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.key_path == key_path && other.value == value
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
- "#{key_path}#{value}" <=> "#{other.key_path}#{other.value}"
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/sorter'
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 = Sorter.array(sorters)
44
+ @sorters = Sorters.array(sorters).uniq
38
45
 
39
46
  freeze
40
47
  end
41
48
 
42
49
  def ==(other)
43
- other.fields.sort == fields.sort &&
44
- other.filters.sort == filters.sort &&
45
- other.limit == limit &&
46
- other.sorters.sort == sorters.sort
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
@@ -8,5 +8,5 @@
8
8
  #
9
9
 
10
10
  module Dbee
11
- VERSION = '1.0.3'
11
+ VERSION = '1.1.0'
12
12
  end
@@ -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
- expect(subject.hash).to eq("#{config[:name]}#{config[:parent]}".hash)
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 concatenated string hash of name and parent' do
27
- expect(subject.hash).to eq("#{config[:name]}#{config[:parent]}".hash)
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
- expect(subject.hash).to eq("#{config[:name].hash}#{config[:value]}".hash)
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
@@ -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
- specify 'equality compares attributes' do
94
- config = yaml_fixture('models.yaml')['Theaters, Members, and Movies']
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 concatenated string hash of key_path and value' do
32
- expect(subject.hash).to eq("#{config[:key_path]}#{config[:value]}".hash)
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::Sorter do
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', direction: :descending } }
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 key_path and direction' do
32
- expect(subject.hash).to eq("#{config[:key_path]}#{config[:direction]}".hash)
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
- it '#descending? is true' do
68
- expect(subject.descending?).to be true
69
- end
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
@@ -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.3
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-27 00:00:00.000000000 Z
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/sorter.rb
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/sorter_spec.rb
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/sorter_spec.rb
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
@@ -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