dbee 2.0.1 → 2.1.1

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: 4cccb1a5e9bf46985f887caa422c34401a0fcfd6b792b47e7a58ca1111ed6bef
4
- data.tar.gz: 9814c17b3483ebb7d5303eb95576e2f94321cae1cd4db219cb57da564316c43b
3
+ metadata.gz: b3c9c1444028bdfd5a4aa9eeb8c98055184f1b2cec2b819376e3f5344850d3b9
4
+ data.tar.gz: '059ac6adca29bae5a1eb0fc9f13247159047f1e8c82b3b31398d4492913ef595'
5
5
  SHA512:
6
- metadata.gz: fdf4aa6edf57d80e1c6ba29db2b4776f6e6acab607962b093648fd3f6fad812c17d7f15d664b0fe14becd46bcd71f785ea643ad4ffdac2d61154011feb27471d
7
- data.tar.gz: 472bfcd22ebee89c2c15f789c90f1147d2938941283fc4a29400e7316de42166ffc34497ee7d1ec447e7be4e26cc3276c2e06d7260976fb3dc38633e808b85b0
6
+ metadata.gz: f67474cd84508029e3f3ca6e91ee2a1192b3cb1f8bf36f6b2d18a9c51e75ba3af897b01ea16676c6c79b000bd8d44d1381a7785fa56a9b81b906d47332e1c687
7
+ data.tar.gz: 6d6d061db4ef0c39cc1af32368d725c8354af5fc143a562f10e3beed7c3d260f7ddc93ab2aaff6016c483f370e9ccfec5e54c72dffcb8044c723025cb40dfdb5
@@ -1,6 +1,13 @@
1
- Metrics/LineLength:
1
+ AllCops:
2
+ TargetRubyVersion: 2.5
3
+ NewCops: enable
4
+
5
+ Layout/LineLength:
2
6
  Max: 100
3
7
 
8
+ Metrics/AbcSize:
9
+ Max: 16
10
+
4
11
  Metrics/BlockLength:
5
12
  ExcludedMethods:
6
13
  - let
@@ -10,14 +17,8 @@ Metrics/BlockLength:
10
17
  - specify
11
18
  - define
12
19
 
13
- Metrics/MethodLength:
14
- Max: 25
15
-
16
- AllCops:
17
- TargetRubyVersion: 2.4
18
-
19
- Metrics/AbcSize:
20
- Max: 16
21
-
22
20
  Metrics/ClassLength:
23
21
  Max: 125
22
+
23
+ Metrics/MethodLength:
24
+ Max: 25
@@ -1 +1 @@
1
- 2.6.3
1
+ 2.6.6
@@ -4,9 +4,9 @@ env:
4
4
  language: ruby
5
5
  rvm:
6
6
  # Build on the latest stable of all supported Rubies (https://www.ruby-lang.org/en/downloads/):
7
- - 2.4.6
8
- - 2.5.5
9
- - 2.6.3
7
+ - 2.5.8
8
+ - 2.6.6
9
+ - 2.7.1
10
10
  cache: bundler
11
11
  before_script:
12
12
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
@@ -1,3 +1,45 @@
1
+ # 2.1.1 (July 14th, 2020)
2
+
3
+ * Removed guard that ensured a query has at least one field to establish a more rational base-case.
4
+
5
+ # 2.1.0 (July 13th, 2020)
6
+
7
+ ### Additions:
8
+
9
+ * Added Dbee::Query::Field#aggregator (such as ave, min, max, sum, etc.)
10
+ * Added Dbee::Query::Field#filters (allows for doing select column filtering)
11
+
12
+ ### Changes:
13
+
14
+ * Bumped minimum Ruby version to 2.5
15
+
16
+ # 2.0.3 (January 7th, 2020)
17
+
18
+ ### Fixes:
19
+
20
+ * Constant resolution will now explicitly set inherit to false when calling `Object#const_defined?` and `Object#const_get`. This should equate to less false positives. For example:
21
+
22
+ ```ruby
23
+ class A; end
24
+
25
+ module B
26
+ class A; end
27
+ class C; end
28
+ end
29
+ ```
30
+
31
+ If `B::A` is the desired class, it would not be suitable to just declare an association on `A` as that would resolve explicitly to `::A`. It also means C cannot be auto-resolved without prefixing/sharing the namespace with parent association `A`.
32
+
33
+ # 2.0.2 (November 7th, 2019)
34
+
35
+ ### Additions:
36
+
37
+ * As of 2019-11-07, it is not recommended to use Ruby 2.3, but support was requested and added for Ruby 2.3.8. This is subject to being deprecated with next version.
38
+
39
+ ### Fixes:
40
+
41
+ * Constantizing during inflection will now first check Object#const_defined? and if it is missing, it will now call Object#const_missing. This should work better with auto-loaded environments where constant names may collide, since Object#const_get will traverse down the entire hierarchy and may lead to false positives.
42
+
1
43
  # 2.0.0 (September 3rd, 2019)
2
44
 
3
45
  ### Additions:
data/README.md CHANGED
@@ -363,6 +363,22 @@ You execute a Query against a Data Model, using a Provider. The sample provider
363
363
 
364
364
  Here are some sample executions based off the preceding examples:
365
365
 
366
+ ##### Base Case
367
+
368
+ If a query has no fields then it is implied you would like all fields on the root table. For example:
369
+
370
+ ````ruby
371
+ require 'dbee/providers/active_record_provider'
372
+
373
+ class Practice < Dbee::Base; end
374
+
375
+ provider = Dbee::Providers::ActiveRecordProvider.new
376
+ query = {}
377
+ sql = Dbee.sql(Practice, query, provider)
378
+ ````
379
+
380
+ It equivalent to saying: `SELECT practices.* FROM practices`. This helps to establish a deterministic base-case: it returns the same implicit columns that is independent of sql joins (sorters and/or filters may require sql joins.)
381
+
366
382
  ##### Code-First Execution
367
383
 
368
384
  ````ruby
@@ -407,6 +423,129 @@ sql = Dbee.sql(model, query, provider)
407
423
 
408
424
  The above examples showed how to use a plugin provider, see the plugin provider's documentation for more information about its options and use.
409
425
 
426
+ #### Aggregation
427
+
428
+ Fields can be configured to use aggregation by setting its `aggregator` attribute. For example, say we wanted to count the number of patients per practice:
429
+
430
+ **Data Model**:
431
+
432
+ ````yaml
433
+ name: practice
434
+ models:
435
+ - name: patients
436
+ constraints:
437
+ - type: reference
438
+ name: practice_id
439
+ parent: id
440
+ ````
441
+
442
+ **Query**:
443
+
444
+ ````ruby
445
+ query = {
446
+ fields: [
447
+ {
448
+ key_path: 'id',
449
+ display: 'Practice ID #',
450
+ },
451
+ {
452
+ key_path: 'name',
453
+ display: 'Practice Name',
454
+ },
455
+ {
456
+ key_path: 'patients.id',
457
+ display: 'Total Patients',
458
+ aggregator: :count
459
+ },
460
+ ]
461
+ ````
462
+
463
+ An example of a materialized result would be something akin to:
464
+
465
+ Practice ID # | Practice Name | Total Patients
466
+ ------------- | --------------- | --------------
467
+ 1 | Families Choice | 293
468
+ 2 | Awesome Choice | 2305
469
+ 3 | Best Value | 1200
470
+
471
+ A complete list of aggregator values can be found by inspecting the `Dbee::Query::Field::Aggregator` constant.
472
+
473
+ #### Field/Column Level Filtering & Pivoting
474
+
475
+ Fields can also have filters which provide post-filtering (on the select-level instead of at query-level.) This can be used in conjunction with aggregate functions to provide pivoting. For example:
476
+
477
+ **Data/Schema Example**:
478
+
479
+ patients:
480
+
481
+ id | first | last
482
+ -- | ----- | -----
483
+ 1 | frank | rizzo
484
+
485
+ patient_fields:
486
+
487
+ id | patient_id | key | value
488
+ -- | ---------- | --------------- | -----
489
+ 1 | 1 | dob | 1900-01-01
490
+ 2 | 1 | drivers_license | ABC123
491
+
492
+ **Model Configuration**:
493
+
494
+ ````yaml
495
+ name: patients
496
+ models:
497
+ - name: patient_fields
498
+ constraints:
499
+ - type: reference
500
+ parent: id
501
+ name: patient_id
502
+ ````
503
+
504
+ **Query**:
505
+
506
+ ````ruby
507
+ query = {
508
+ fields: [
509
+ {
510
+ key_path: 'id',
511
+ display: 'ID #'
512
+ },
513
+ {
514
+ key_path: 'first',
515
+ display: 'First Name'
516
+ },
517
+ {
518
+ aggregator: :max,
519
+ key_path: 'patient_fields.value',
520
+ display: 'Date of Birth',
521
+ filters: [
522
+ {
523
+ key_path: 'patient_fields.key',
524
+ value: 'dob'
525
+ }
526
+ ]
527
+ },
528
+ {
529
+ aggregator: :max,
530
+ key_path: 'patient_fields.value',
531
+ display: 'Drivers License #',
532
+ filters: [
533
+ {
534
+ key_path: 'patient_fields.key',
535
+ value: 'drivers_license'
536
+ }
537
+ ]
538
+ }
539
+ }
540
+ }
541
+ ````
542
+
543
+ Executing the query above against the data and model would yield:
544
+
545
+ ID # | First Name | Date of Birth | Drivers License #
546
+ -- | ---------- | ------------- | -----------------
547
+ 1 | frank | 1900-01-01 | ABC123
548
+
410
549
 
411
550
  ## Contributing
412
551
 
@@ -15,20 +15,28 @@ Gem::Specification.new do |s|
15
15
  s.email = ['mruggio@bluemarblepayroll.com']
16
16
  s.files = `git ls-files`.split("\n")
17
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
18
+ s.bindir = 'exe'
19
+ s.executables = []
19
20
  s.homepage = 'https://github.com/bluemarblepayroll/dbee'
20
21
  s.license = 'MIT'
22
+ s.metadata = {
23
+ 'bug_tracker_uri' => 'https://github.com/bluemarblepayroll/dbee/issues',
24
+ 'changelog_uri' => 'https://github.com/bluemarblepayroll/dbee/blob/master/CHANGELOG.md',
25
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/dbee',
26
+ 'homepage_uri' => s.homepage,
27
+ 'source_code_uri' => s.homepage
28
+ }
21
29
 
22
- s.required_ruby_version = '>= 2.4.6'
30
+ s.required_ruby_version = '>= 2.5'
23
31
 
24
- s.add_dependency('acts_as_hashable', '~>1', '>=1.1.0')
32
+ s.add_dependency('acts_as_hashable', '~>1', '>=1.2.0')
25
33
  s.add_dependency('dry-inflector', '~>0')
26
34
 
27
35
  s.add_development_dependency('guard-rspec', '~>4.7')
28
36
  s.add_development_dependency('pry', '~>0')
29
37
  s.add_development_dependency('rake', '~> 13')
30
38
  s.add_development_dependency('rspec')
31
- s.add_development_dependency('rubocop', '~>0.75.1')
32
- s.add_development_dependency('simplecov', '~>0.17.0')
33
- s.add_development_dependency('simplecov-console', '~>0.5.0')
39
+ s.add_development_dependency('rubocop', '~>0.88.0')
40
+ s.add_development_dependency('simplecov', '~>0.18.5')
41
+ s.add_development_dependency('simplecov-console', '~>0.7.0')
34
42
  end
File without changes
@@ -12,6 +12,7 @@ require 'dry/inflector'
12
12
  require 'forwardable'
13
13
 
14
14
  require_relative 'dbee/base'
15
+ require_relative 'dbee/constant_resolver'
15
16
  require_relative 'dbee/key_chain'
16
17
  require_relative 'dbee/key_path'
17
18
  require_relative 'dbee/model'
@@ -0,0 +1,34 @@
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
+ # This class is responsible for turning strings and symbols into constants.
12
+ # It does not deal with inflection, simply just constant resolution.
13
+ class ConstantResolver
14
+ # Only use Module constant resolution if a string or symbol was passed in.
15
+ # Any other type is defined as an acceptable constant and is simply returned.
16
+ def constantize(value)
17
+ value.is_a?(String) || value.is_a?(Symbol) ? object_constant(value) : value
18
+ end
19
+
20
+ private
21
+
22
+ # If the constant has been loaded, we can safely use it through const_get.
23
+ # If the constant has not been loaded, we need to defer to const_missing to resolve it.
24
+ # If we blindly call const_get, it may return false positives for namespaced constants
25
+ # or anything nested.
26
+ def object_constant(value)
27
+ if Object.const_defined?(value, false)
28
+ Object.const_get(value, false)
29
+ else
30
+ Object.const_missing(value)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -19,16 +19,17 @@ module Dbee
19
19
  raise ArgumentError, 'inflector is required' unless inflector
20
20
  raise ArgumentError, 'name is required' if name.to_s.empty?
21
21
 
22
- @on_class_name = on_class_name
23
- @inflector = inflector
24
- @name = name.to_s
25
- @opts = opts || {}
22
+ @on_class_name = on_class_name
23
+ @inflector = inflector
24
+ @name = name.to_s
25
+ @opts = opts || {}
26
+ @constant_resolver = ConstantResolver.new
26
27
 
27
28
  freeze
28
29
  end
29
30
 
30
31
  def model_constant
31
- constantize(class_name)
32
+ constant_resolver.constantize(class_name)
32
33
  end
33
34
 
34
35
  def constraints
@@ -37,17 +38,18 @@ module Dbee
37
38
 
38
39
  private
39
40
 
41
+ attr_reader :constant_resolver
42
+
40
43
  def class_name
41
44
  opts[:model] || relative_class_name
42
45
  end
43
46
 
47
+ # This will automatically prefix the name of the module within the current classes
48
+ # hierarchy. If the class does not happen to be in the same namespace then it needs
49
+ # to be explicitly set in the association using 'model' option.
44
50
  def relative_class_name
45
51
  (on_class_name.split('::')[0...-1] + [inflector.classify(name)]).join('::')
46
52
  end
47
-
48
- def constantize(value)
49
- value.is_a?(String) || value.is_a?(Symbol) ? Object.const_get(value) : value
50
- end
51
53
  end
52
54
  end
53
55
  end
@@ -21,37 +21,35 @@ module Dbee
21
21
  extend Forwardable
22
22
  acts_as_hashable
23
23
 
24
- class NoFieldsError < StandardError; end
25
-
26
- attr_reader :fields, :filters, :limit, :sorters
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
-
34
- def initialize(fields:, filters: [], limit: nil, sorters: [])
35
- @fields = Field.array(fields)
36
-
37
- # If no fields were passed into a query then we will have no data to return.
38
- # Let's raise a hard error here and let the consumer deal with it since this may
39
- # have implications in downstream SQL generators.
40
- raise NoFieldsError if @fields.empty?
41
-
42
- @filters = Filters.array(filters).uniq
43
- @limit = limit.to_s.empty? ? nil : limit.to_i
44
- @sorters = Sorters.array(sorters).uniq
24
+ attr_reader :fields,
25
+ :filters,
26
+ :limit,
27
+ :sorters
28
+
29
+ def_delegator :fields, :sort, :sorted_fields
30
+ def_delegator :filters, :sort, :sorted_filters
31
+ def_delegator :sorters, :sort, :sorted_sorters
32
+
33
+ def initialize(
34
+ fields: [],
35
+ filters: [],
36
+ limit: nil,
37
+ sorters: []
38
+ )
39
+ @fields = Field.array(fields)
40
+ @filters = Filters.array(filters).uniq
41
+ @limit = limit.to_s.empty? ? nil : limit.to_i
42
+ @sorters = Sorters.array(sorters).uniq
45
43
 
46
44
  freeze
47
45
  end
48
46
 
49
47
  def ==(other)
50
48
  other.instance_of?(self.class) &&
49
+ other.limit == limit &&
51
50
  other.sorted_fields == sorted_fields &&
52
51
  other.sorted_filters == sorted_filters &&
53
- other.sorted_sorters == sorted_sorters &&
54
- other.limit == limit
52
+ other.sorted_sorters == sorted_sorters
55
53
  end
56
54
  alias eql? ==
57
55
 
@@ -62,7 +60,11 @@ module Dbee
62
60
  private
63
61
 
64
62
  def key_paths
65
- (fields.map(&:key_path) + filters.map(&:key_path) + sorters.map(&:key_path))
63
+ (
64
+ fields.flat_map(&:key_paths) +
65
+ filters.map(&:key_path) +
66
+ sorters.map(&:key_path)
67
+ )
66
68
  end
67
69
  end
68
70
  end
@@ -15,24 +15,55 @@ module Dbee
15
15
  class Field
16
16
  acts_as_hashable
17
17
 
18
- attr_reader :key_path, :display
18
+ module Aggregator
19
+ AVE = :ave
20
+ COUNT = :count
21
+ MAX = :max
22
+ MIN = :min
23
+ SUM = :sum
24
+ end
25
+ include Aggregator
26
+
27
+ attr_reader :aggregator, :display, :filters, :key_path
19
28
 
20
- def initialize(key_path:, display: nil)
29
+ def initialize(
30
+ aggregator: nil,
31
+ display: nil,
32
+ filters: [],
33
+ key_path:
34
+ )
21
35
  raise ArgumentError, 'key_path is required' if key_path.to_s.empty?
22
36
 
23
- @key_path = KeyPath.get(key_path)
24
- @display = (display.to_s.empty? ? key_path : display).to_s
37
+ @aggregator = aggregator ? Aggregator.const_get(aggregator.to_s.upcase.to_sym) : nil
38
+ @display = (display.to_s.empty? ? key_path : display).to_s
39
+ @filters = Filters.array(filters).uniq
40
+ @key_path = KeyPath.get(key_path)
25
41
 
26
42
  freeze
27
43
  end
28
44
 
45
+ def filters?
46
+ filters.any?
47
+ end
48
+
49
+ def aggregator?
50
+ !aggregator.nil?
51
+ end
52
+
29
53
  def hash
30
- "#{key_path}#{display}".hash
54
+ [
55
+ aggregator,
56
+ display,
57
+ filters,
58
+ key_path
59
+ ].hash
31
60
  end
32
61
 
33
62
  def ==(other)
34
63
  other.instance_of?(self.class) &&
64
+ other.aggregator == aggregator &&
35
65
  other.key_path == key_path &&
66
+ other.filters == filters &&
36
67
  other.display == display
37
68
  end
38
69
  alias eql? ==
@@ -40,6 +71,10 @@ module Dbee
40
71
  def <=>(other)
41
72
  "#{key_path}#{display}" <=> "#{other.key_path}#{other.display}"
42
73
  end
74
+
75
+ def key_paths
76
+ [key_path] + filters.map(&:key_path)
77
+ end
43
78
  end
44
79
  end
45
80
  end
@@ -8,5 +8,5 @@
8
8
  #
9
9
 
10
10
  module Dbee
11
- VERSION = '2.0.1'
11
+ VERSION = '2.1.1'
12
12
  end
@@ -0,0 +1,53 @@
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::ConstantResolver do
13
+ module A
14
+ class B; end
15
+ class E; end
16
+ end
17
+
18
+ class B; end
19
+
20
+ module C
21
+ class D; end
22
+ class E; end
23
+
24
+ module F
25
+ class G; end
26
+ end
27
+ end
28
+
29
+ it 'resolves nested constant with the same as an ancestor constants sibling' do
30
+ expect(subject.constantize('A::B')).to eq(::A::B)
31
+ end
32
+
33
+ it 'resolves root constant' do
34
+ expect(subject.constantize('B')).to eq(::B)
35
+ end
36
+
37
+ it 'does not resolve constant in a different parent module' do
38
+ expect { subject.constantize('C::B') }.to raise_error(NameError)
39
+ end
40
+
41
+ it 'does not resolve constant in a different parent module' do
42
+ expect { subject.constantize('D') }.to raise_error(NameError)
43
+ end
44
+
45
+ it 'resolves same leaf constants specific to their parents' do
46
+ expect(subject.constantize('A::E')).to eq(::A::E)
47
+ expect(subject.constantize('C::E')).to eq(::C::E)
48
+ end
49
+
50
+ it 'does not resolve constant without its parent' do
51
+ expect { subject.constantize('F') }.to raise_error(NameError)
52
+ end
53
+ end
@@ -10,6 +10,31 @@
10
10
  require 'spec_helper'
11
11
 
12
12
  describe Dbee::Query::Field do
13
+ let(:config) do
14
+ {
15
+ display: 'd',
16
+ key_path: 'a.b.c'
17
+ }
18
+ end
19
+
20
+ let(:config_with_aggregation_and_filters) do
21
+ config.merge(
22
+ aggregator: :ave,
23
+ filters: [
24
+ {
25
+ key_path: 'a.b',
26
+ value: 'something'
27
+ }
28
+ ]
29
+ )
30
+ end
31
+
32
+ subject { described_class.new(config_with_aggregation_and_filters) }
33
+
34
+ let(:subject_without_aggregation_and_filters) do
35
+ described_class.new(config)
36
+ end
37
+
13
38
  it 'should act as hashable' do
14
39
  expect(described_class).to respond_to(:make)
15
40
  expect(described_class).to respond_to(:array)
@@ -24,16 +49,19 @@ describe Dbee::Query::Field do
24
49
  end
25
50
 
26
51
  context 'equality' do
27
- let(:config) { { key_path: 'a.b.c', display: 'd' } }
52
+ specify '#hash produces same output as [aggregator, key_path, and display]' do
53
+ expected = [
54
+ subject.aggregator,
55
+ subject.display,
56
+ subject.filters,
57
+ subject.key_path
58
+ ].hash
28
59
 
29
- subject { described_class.new(config) }
30
-
31
- specify '#hash produces same output as concatenated string hash of key_path and display' do
32
- expect(subject.hash).to eq("#{config[:key_path]}#{config[:display]}".hash)
60
+ expect(subject.hash).to eq(expected)
33
61
  end
34
62
 
35
63
  specify '#== and #eql? compare attributes' do
36
- object2 = described_class.new(config)
64
+ object2 = described_class.new(config_with_aggregation_and_filters)
37
65
 
38
66
  expect(subject).to eq(object2)
39
67
  expect(subject).to eql(object2)
@@ -44,4 +72,24 @@ describe Dbee::Query::Field do
44
72
  expect(subject).not_to eq(nil)
45
73
  end
46
74
  end
75
+
76
+ describe '#aggregator?' do
77
+ it 'returns true if not nil' do
78
+ expect(subject.aggregator?).to be true
79
+ end
80
+
81
+ it 'returns false if nil' do
82
+ expect(subject_without_aggregation_and_filters.aggregator?).to be false
83
+ end
84
+ end
85
+
86
+ describe '#filters?' do
87
+ it 'returns true if at least one filter' do
88
+ expect(subject.filters?).to be true
89
+ end
90
+
91
+ it 'returns false if nil' do
92
+ expect(subject_without_aggregation_and_filters.filters?).to be false
93
+ end
94
+ end
47
95
  end
@@ -36,14 +36,6 @@ describe Dbee::Query do
36
36
  end
37
37
 
38
38
  describe '#initialize' do
39
- it 'should raise an ArgumentError if fields keyword is missing' do
40
- expect { described_class.new }.to raise_error(ArgumentError)
41
- end
42
-
43
- it 'should raise a NoFieldsError if no fields were passed in' do
44
- expect { described_class.new(fields: []) }.to raise_error(Dbee::Query::NoFieldsError)
45
- end
46
-
47
39
  it 'should remove duplicate filters (keep first instance)' do
48
40
  query_hash = {
49
41
  fields: [
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: 2.0.1
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-15 00:00:00.000000000 Z
11
+ date: 2020-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: acts_as_hashable
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '1'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 1.1.0
22
+ version: 1.2.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '1'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 1.1.0
32
+ version: 1.2.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: dry-inflector
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -106,50 +106,49 @@ dependencies:
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: 0.75.1
109
+ version: 0.88.0
110
110
  type: :development
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: 0.75.1
116
+ version: 0.88.0
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: simplecov
119
119
  requirement: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: 0.17.0
123
+ version: 0.18.5
124
124
  type: :development
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: 0.17.0
130
+ version: 0.18.5
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: simplecov-console
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: 0.5.0
137
+ version: 0.7.0
138
138
  type: :development
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: 0.5.0
144
+ version: 0.7.0
145
145
  description: " Dbee provides a simple-to-use data modeling and query API. The
146
146
  query API can produce SQL using other ORMs, such as Arel/ActiveRecord. The targeted
147
147
  use-case for Dbee is ad-hoc reporting, so the total SQL feature-set that Dbee supports
148
148
  is rather limited.\n"
149
149
  email:
150
150
  - mruggio@bluemarblepayroll.com
151
- executables:
152
- - console
151
+ executables: []
153
152
  extensions: []
154
153
  extra_rdoc_files: []
155
154
  files:
@@ -167,8 +166,10 @@ files:
167
166
  - Rakefile
168
167
  - bin/console
169
168
  - dbee.gemspec
169
+ - exe/.gitkeep
170
170
  - lib/dbee.rb
171
171
  - lib/dbee/base.rb
172
+ - lib/dbee/constant_resolver.rb
172
173
  - lib/dbee/dsl/association.rb
173
174
  - lib/dbee/dsl/association_builder.rb
174
175
  - lib/dbee/dsl/methods.rb
@@ -203,6 +204,7 @@ files:
203
204
  - lib/dbee/query/sorters/descending.rb
204
205
  - lib/dbee/version.rb
205
206
  - spec/dbee/base_spec.rb
207
+ - spec/dbee/constant_resolver_spec.rb
206
208
  - spec/dbee/key_chain_spec.rb
207
209
  - spec/dbee/key_path_spec.rb
208
210
  - spec/dbee/model/constraints/base_spec.rb
@@ -225,7 +227,12 @@ files:
225
227
  homepage: https://github.com/bluemarblepayroll/dbee
226
228
  licenses:
227
229
  - MIT
228
- metadata: {}
230
+ metadata:
231
+ bug_tracker_uri: https://github.com/bluemarblepayroll/dbee/issues
232
+ changelog_uri: https://github.com/bluemarblepayroll/dbee/blob/master/CHANGELOG.md
233
+ documentation_uri: https://www.rubydoc.info/gems/dbee
234
+ homepage_uri: https://github.com/bluemarblepayroll/dbee
235
+ source_code_uri: https://github.com/bluemarblepayroll/dbee
229
236
  post_install_message:
230
237
  rdoc_options: []
231
238
  require_paths:
@@ -234,7 +241,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
234
241
  requirements:
235
242
  - - ">="
236
243
  - !ruby/object:Gem::Version
237
- version: 2.4.6
244
+ version: '2.5'
238
245
  required_rubygems_version: !ruby/object:Gem::Requirement
239
246
  requirements:
240
247
  - - ">="
@@ -247,6 +254,7 @@ specification_version: 4
247
254
  summary: Adhoc Reporting SQL Generator
248
255
  test_files:
249
256
  - spec/dbee/base_spec.rb
257
+ - spec/dbee/constant_resolver_spec.rb
250
258
  - spec/dbee/key_chain_spec.rb
251
259
  - spec/dbee/key_path_spec.rb
252
260
  - spec/dbee/model/constraints/base_spec.rb