cuprum-collections 0.4.0 → 0.5.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.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +73 -0
  3. data/README.md +5 -5
  4. data/lib/cuprum/collections/association.rb +9 -28
  5. data/lib/cuprum/collections/associations/belongs_to.rb +1 -8
  6. data/lib/cuprum/collections/associations/has_many.rb +1 -10
  7. data/lib/cuprum/collections/associations/has_one.rb +1 -10
  8. data/lib/cuprum/collections/basic/collection.rb +56 -49
  9. data/lib/cuprum/collections/basic/command.rb +22 -88
  10. data/lib/cuprum/collections/basic/commands/assign_one.rb +2 -6
  11. data/lib/cuprum/collections/basic/commands/build_one.rb +1 -4
  12. data/lib/cuprum/collections/basic/commands/destroy_one.rb +4 -8
  13. data/lib/cuprum/collections/basic/commands/find_many.rb +4 -24
  14. data/lib/cuprum/collections/basic/commands/find_matching.rb +5 -21
  15. data/lib/cuprum/collections/basic/commands/find_one.rb +3 -20
  16. data/lib/cuprum/collections/basic/commands/insert_one.rb +3 -6
  17. data/lib/cuprum/collections/basic/commands/update_one.rb +3 -6
  18. data/lib/cuprum/collections/basic/commands/validate_one.rb +13 -18
  19. data/lib/cuprum/collections/basic/query.rb +26 -40
  20. data/lib/cuprum/collections/basic/repository.rb +4 -3
  21. data/lib/cuprum/collections/basic/scopes/all_scope.rb +25 -0
  22. data/lib/cuprum/collections/basic/scopes/base.rb +32 -0
  23. data/lib/cuprum/collections/basic/scopes/builder.rb +39 -0
  24. data/lib/cuprum/collections/basic/scopes/conjunction_scope.rb +20 -0
  25. data/lib/cuprum/collections/basic/scopes/criteria_scope.rb +62 -0
  26. data/lib/cuprum/collections/basic/scopes/disjunction_scope.rb +20 -0
  27. data/lib/cuprum/collections/basic/scopes/none_scope.rb +33 -0
  28. data/lib/cuprum/collections/basic/scopes.rb +23 -0
  29. data/lib/cuprum/collections/basic.rb +1 -0
  30. data/lib/cuprum/collections/collection.rb +24 -82
  31. data/lib/cuprum/collections/collection_command.rb +116 -0
  32. data/lib/cuprum/collections/commands/abstract_find_many.rb +11 -21
  33. data/lib/cuprum/collections/commands/abstract_find_matching.rb +43 -24
  34. data/lib/cuprum/collections/commands/abstract_find_one.rb +7 -10
  35. data/lib/cuprum/collections/commands/associations/find_many.rb +3 -8
  36. data/lib/cuprum/collections/commands/associations/require_many.rb +5 -5
  37. data/lib/cuprum/collections/commands/create.rb +3 -3
  38. data/lib/cuprum/collections/commands/find_one_matching.rb +6 -6
  39. data/lib/cuprum/collections/commands/query_command.rb +19 -0
  40. data/lib/cuprum/collections/commands/update.rb +3 -3
  41. data/lib/cuprum/collections/commands/upsert.rb +10 -10
  42. data/lib/cuprum/collections/commands.rb +1 -0
  43. data/lib/cuprum/collections/constraints/ordering.rb +2 -2
  44. data/lib/cuprum/collections/errors/abstract_find_error.rb +25 -42
  45. data/lib/cuprum/collections/errors/extra_attributes.rb +3 -3
  46. data/lib/cuprum/collections/errors/failed_validation.rb +2 -2
  47. data/lib/cuprum/collections/errors/invalid_parameters.rb +2 -2
  48. data/lib/cuprum/collections/errors/invalid_query.rb +10 -16
  49. data/lib/cuprum/collections/errors/missing_default_contract.rb +1 -1
  50. data/lib/cuprum/collections/errors/unknown_operator.rb +1 -1
  51. data/lib/cuprum/collections/queries.rb +31 -0
  52. data/lib/cuprum/collections/query.rb +50 -62
  53. data/lib/cuprum/collections/relation.rb +5 -383
  54. data/lib/cuprum/collections/relations/cardinality.rb +66 -0
  55. data/lib/cuprum/collections/relations/options.rb +18 -0
  56. data/lib/cuprum/collections/relations/parameters.rb +217 -0
  57. data/lib/cuprum/collections/relations/primary_keys.rb +23 -0
  58. data/lib/cuprum/collections/relations/scope.rb +65 -0
  59. data/lib/cuprum/collections/relations.rb +14 -0
  60. data/lib/cuprum/collections/repository.rb +5 -5
  61. data/lib/cuprum/collections/resource.rb +10 -41
  62. data/lib/cuprum/collections/rspec/contracts/association_contracts.rb +80 -90
  63. data/lib/cuprum/collections/rspec/contracts/collection_contracts.rb +69 -111
  64. data/lib/cuprum/collections/rspec/contracts/command_contracts.rb +42 -1335
  65. data/lib/cuprum/collections/rspec/contracts/query_contracts.rb +352 -531
  66. data/lib/cuprum/collections/rspec/contracts/relation_contracts.rb +74 -191
  67. data/lib/cuprum/collections/rspec/contracts/repository_contracts.rb +13 -13
  68. data/lib/cuprum/collections/rspec/contracts/scope_contracts.rb +1029 -0
  69. data/lib/cuprum/collections/rspec/contracts/scopes/builder_contracts.rb +856 -0
  70. data/lib/cuprum/collections/rspec/contracts/scopes/composition_contracts.rb +1430 -0
  71. data/lib/cuprum/collections/rspec/contracts/scopes/criteria_contracts.rb +2217 -0
  72. data/lib/cuprum/collections/rspec/contracts/scopes/logical_contracts.rb +297 -0
  73. data/lib/cuprum/collections/rspec/contracts/scopes.rb +13 -0
  74. data/lib/cuprum/collections/rspec/contracts.rb +2 -0
  75. data/lib/cuprum/collections/rspec/deferred/association_examples.rb +2098 -0
  76. data/lib/cuprum/collections/rspec/deferred/collection_examples.rb +338 -0
  77. data/lib/cuprum/collections/rspec/deferred/command_examples.rb +160 -0
  78. data/lib/cuprum/collections/rspec/deferred/commands/assign_one_examples.rb +178 -0
  79. data/lib/cuprum/collections/rspec/deferred/commands/build_one_examples.rb +94 -0
  80. data/lib/cuprum/collections/rspec/deferred/commands/destroy_one_examples.rb +118 -0
  81. data/lib/cuprum/collections/rspec/deferred/commands/find_many_examples.rb +307 -0
  82. data/lib/cuprum/collections/rspec/deferred/commands/find_matching_examples.rb +143 -0
  83. data/lib/cuprum/collections/rspec/deferred/commands/find_one_examples.rb +116 -0
  84. data/lib/cuprum/collections/rspec/deferred/commands/insert_one_examples.rb +103 -0
  85. data/lib/cuprum/collections/rspec/deferred/commands/update_one_examples.rb +99 -0
  86. data/lib/cuprum/collections/rspec/deferred/commands/validate_one_examples.rb +117 -0
  87. data/lib/cuprum/collections/rspec/deferred/commands.rb +8 -0
  88. data/lib/cuprum/collections/rspec/deferred/relation_examples.rb +1437 -0
  89. data/lib/cuprum/collections/rspec/deferred/resource_examples.rb +26 -0
  90. data/lib/cuprum/collections/rspec/deferred.rb +8 -0
  91. data/lib/cuprum/collections/scope.rb +29 -0
  92. data/lib/cuprum/collections/scopes/all.rb +51 -0
  93. data/lib/cuprum/collections/scopes/all_scope.rb +18 -0
  94. data/lib/cuprum/collections/scopes/base.rb +79 -0
  95. data/lib/cuprum/collections/scopes/builder.rb +39 -0
  96. data/lib/cuprum/collections/scopes/building.rb +221 -0
  97. data/lib/cuprum/collections/scopes/composition.rb +162 -0
  98. data/lib/cuprum/collections/scopes/conjunction.rb +44 -0
  99. data/lib/cuprum/collections/scopes/conjunction_scope.rb +12 -0
  100. data/lib/cuprum/collections/scopes/container.rb +65 -0
  101. data/lib/cuprum/collections/scopes/criteria/parser.rb +241 -0
  102. data/lib/cuprum/collections/scopes/criteria.rb +206 -0
  103. data/lib/cuprum/collections/scopes/criteria_scope.rb +12 -0
  104. data/lib/cuprum/collections/scopes/disjunction.rb +45 -0
  105. data/lib/cuprum/collections/scopes/disjunction_scope.rb +12 -0
  106. data/lib/cuprum/collections/scopes/none.rb +62 -0
  107. data/lib/cuprum/collections/scopes/none_scope.rb +18 -0
  108. data/lib/cuprum/collections/scopes.rb +23 -0
  109. data/lib/cuprum/collections/version.rb +2 -2
  110. data/lib/cuprum/collections.rb +14 -9
  111. metadata +61 -15
  112. data/lib/cuprum/collections/basic/query_builder.rb +0 -69
  113. data/lib/cuprum/collections/command.rb +0 -26
  114. data/lib/cuprum/collections/queries/parse.rb +0 -22
  115. data/lib/cuprum/collections/queries/parse_block.rb +0 -206
  116. data/lib/cuprum/collections/queries/parse_strategy.rb +0 -91
  117. data/lib/cuprum/collections/query_builder.rb +0 -61
  118. data/lib/cuprum/collections/rspec/contracts/basic/command_contracts.rb +0 -484
@@ -101,26 +101,10 @@ module Cuprum::Collections::Basic::Commands
101
101
  # @return [Cuprum::Result<Hash{String, Array<Hash{String, Object}>}>] a
102
102
  # hash with the collection name as key and the matching items as
103
103
  # value.
104
-
105
- validate_parameters :call do
106
- keyword :envelope,
107
- Stannum::Constraints::Boolean.new,
108
- default: true
109
- keyword :limit, Integer, optional: true
110
- keyword :offset, Integer, optional: true
111
- keyword :order,
112
- Cuprum::Collections::Constraints::Ordering.new,
113
- optional: true
114
- keyword :scope,
115
- Cuprum::Collections::Basic::Query,
116
- optional: true
117
- keyword :where, Object, optional: true
118
- end
119
-
120
- private
121
-
122
- def build_query
123
- Cuprum::Collections::Basic::Query.new(data)
124
- end
104
+ validate :envelope, :boolean, optional: true
105
+ validate :limit, Integer, optional: true
106
+ validate :offset, Integer, optional: true
107
+ validate :order
108
+ validate :where
125
109
  end
126
110
  end
@@ -11,7 +11,7 @@ module Cuprum::Collections::Basic::Commands
11
11
  class FindOne < Cuprum::Collections::Basic::Command
12
12
  include Cuprum::Collections::Commands::AbstractFindOne
13
13
 
14
- # @!method call(primary_key:, envelope: false, scope: nil)
14
+ # @!method call(primary_key:, envelope: false)
15
15
  # Queries the collection for the item with the given primary key.
16
16
  #
17
17
  # The command will find and return the entity with the given primary key.
@@ -23,27 +23,10 @@ module Cuprum::Collections::Basic::Commands
23
23
  #
24
24
  # @param envelope [Boolean] If true, wraps the result value in a Hash.
25
25
  # @param primary_key [Object] The primary key of the requested item.
26
- # @param scope [Cuprum::Collections::Basic::Query, nil] Optional scope for
27
- # the query. The item must match the scope as well as the primary key.
28
26
  #
29
27
  # @return [Cuprum::Result<Hash{String, Object}>] a result with the
30
28
  # requested item.
31
- validate_parameters :call do
32
- keyword :envelope, Stannum::Constraints::Boolean.new, default: true
33
- keyword :primary_key, Object
34
- keyword :scope, Cuprum::Collections::Basic::Query, optional: true
35
- end
36
-
37
- private
38
-
39
- def build_query
40
- Cuprum::Collections::Basic::Query.new(data)
41
- end
42
-
43
- def process(primary_key:, envelope: false, scope: nil)
44
- step { validate_primary_key(primary_key) }
45
-
46
- super
47
- end
29
+ validate :envelope, :boolean, optional: true
30
+ validate :primary_key
48
31
  end
49
32
  end
@@ -18,10 +18,7 @@ module Cuprum::Collections::Basic::Commands
18
18
  # @param entity [Hash] The collection entity to persist.
19
19
  #
20
20
  # @return [Cuprum::Result<Hash>] the persisted entity.
21
- validate_parameters :call do
22
- keyword :entity,
23
- Stannum::Constraints::Types::HashWithStringKeys.new
24
- end
21
+ validate :entity
25
22
 
26
23
  private
27
24
 
@@ -34,14 +31,14 @@ module Cuprum::Collections::Basic::Commands
34
31
  error = Cuprum::Collections::Errors::AlreadyExists.new(
35
32
  attribute_name: primary_key_name,
36
33
  attribute_value: value,
37
- collection_name: collection_name,
34
+ collection_name:,
38
35
  primary_key: true
39
36
  )
40
37
  failure(error)
41
38
  end
42
39
 
43
40
  def process(entity:)
44
- step { find_existing(entity: entity) }
41
+ step { find_existing(entity:) }
45
42
 
46
43
  data << tools.hash_tools.deep_dup(entity)
47
44
 
@@ -18,10 +18,7 @@ module Cuprum::Collections::Basic::Commands
18
18
  # @param entity [Hash] The collection entity to persist.
19
19
  #
20
20
  # @return [Cuprum::Result<Hash>] the persisted entity.
21
- validate_parameters :call do
22
- keyword :entity,
23
- Stannum::Constraints::Types::HashWithStringKeys.new
24
- end
21
+ validate :entity
25
22
 
26
23
  private
27
24
 
@@ -34,14 +31,14 @@ module Cuprum::Collections::Basic::Commands
34
31
  error = Cuprum::Collections::Errors::NotFound.new(
35
32
  attribute_name: primary_key_name,
36
33
  attribute_value: entity[primary_key_name.to_s],
37
- collection_name: collection_name,
34
+ collection_name:,
38
35
  primary_key: true
39
36
  )
40
37
  failure(error)
41
38
  end
42
39
 
43
40
  def process(entity:)
44
- index = step { find_existing(entity: entity) }
41
+ index = step { find_existing(entity:) }
45
42
 
46
43
  entity = data[index].merge(entity)
47
44
 
@@ -24,13 +24,8 @@ module Cuprum::Collections::Basic::Commands
24
24
  # @param entity [Hash] The collection entity to validate.
25
25
  #
26
26
  # @return [Cuprum::Result<Hash>] the validated entity.
27
- validate_parameters :call do
28
- keyword :contract,
29
- Stannum::Constraints::Base,
30
- optional: true
31
- keyword :entity,
32
- Stannum::Constraints::Types::HashWithStringKeys.new
33
- end
27
+ validate :contract, Stannum::Constraints::Base, optional: true
28
+ validate :entity
34
29
 
35
30
  private
36
31
 
@@ -45,25 +40,25 @@ module Cuprum::Collections::Basic::Commands
45
40
  failure(error)
46
41
  end
47
42
 
48
- def process(entity:, contract: nil)
49
- contract =
50
- step { contract_or_default(contract: contract, entity: entity) }
51
-
52
- step { validate_entity(contract: contract, entity: entity) }
53
-
54
- entity
55
- end
56
-
57
- def validate_entity(contract:, entity:)
43
+ def match_entity(contract:, entity:)
58
44
  valid, errors = contract.match(entity)
59
45
 
60
46
  return if valid
61
47
 
62
48
  error = Cuprum::Collections::Errors::FailedValidation.new(
63
49
  entity_class: entity.class,
64
- errors: errors
50
+ errors:
65
51
  )
66
52
  failure(error)
67
53
  end
54
+
55
+ def process(entity:, contract: nil)
56
+ contract =
57
+ step { contract_or_default(contract:, entity:) }
58
+
59
+ step { match_entity(contract:, entity:) }
60
+
61
+ entity
62
+ end
68
63
  end
69
64
  end
@@ -1,24 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'cuprum/collections/basic'
4
- require 'cuprum/collections/basic/query_builder'
4
+ require 'cuprum/collections/basic/scopes/all_scope'
5
5
  require 'cuprum/collections/query'
6
6
 
7
7
  module Cuprum::Collections::Basic
8
8
  # Concrete implementation of a Query for an in-memory collection.
9
9
  class Query < Cuprum::Collections::Query
10
- include Enumerable
11
-
12
10
  # @param data [Array<Hash>] The current data in the collection. Should be an
13
11
  # Array of Hashes, each of which represents one item in the collection.
14
- def initialize(data)
15
- super()
16
-
17
- @data = data
18
- @filters = []
19
- @limit = nil
20
- @offset = nil
21
- @order = {}
12
+ # @param scope [Cuprum::Collections::Scopes::Base] the base scope for the
13
+ # query. Defaults to nil.
14
+ def initialize(data, scope: nil)
15
+ super(scope:)
16
+
17
+ @data = data
22
18
  end
23
19
 
24
20
  # Iterates through the collection, yielding each item matching the query.
@@ -48,10 +44,10 @@ module Cuprum::Collections::Basic
48
44
  # @see #order
49
45
  # @see #to_a
50
46
  # @see #where
51
- def each(&block)
52
- return enum_for(:each) unless block_given?
47
+ def each(...)
48
+ return enum_for(:each, ...) unless block_given?
53
49
 
54
- filtered_data.each(&block)
50
+ scoped_data.each(...)
55
51
  end
56
52
 
57
53
  # Checks for the presence of collection items matching the query.
@@ -62,9 +58,9 @@ module Cuprum::Collections::Basic
62
58
  #
63
59
  # @return [Boolean] true if any items match the query; otherwise false.
64
60
  def exists?
65
- data.any? do |item|
66
- @filters.all? { |filter| filter.call(item) }
67
- end
61
+ return data.any? unless scope
62
+
63
+ data.any? { |item| scope.match?(item:) }
68
64
  end
69
65
 
70
66
  # Returns an array containing each collection item matching the query.
@@ -90,23 +86,13 @@ module Cuprum::Collections::Basic
90
86
  # @see #order
91
87
  # @see #where
92
88
  def to_a
93
- filtered_data
89
+ scoped_data
94
90
  end
95
91
 
96
92
  protected
97
93
 
98
- def query_builder
99
- Cuprum::Collections::Basic::QueryBuilder.new(self)
100
- end
101
-
102
94
  def reset!
103
- @filtered_data = nil
104
-
105
- self
106
- end
107
-
108
- def with_filters(filters)
109
- @filters += filters
95
+ @scoped_data = nil
110
96
 
111
97
  self
112
98
  end
@@ -115,14 +101,6 @@ module Cuprum::Collections::Basic
115
101
 
116
102
  attr_reader :data
117
103
 
118
- attr_reader :filters
119
-
120
- def apply_filters(data)
121
- data.select do |item|
122
- @filters.all? { |filter| filter.call(item) }
123
- end
124
- end
125
-
126
104
  def apply_limit_offset(data)
127
105
  return data[@offset...(@offset + @limit)] || [] if @limit && @offset
128
106
  return data[0...@limit] if @limit
@@ -148,10 +126,18 @@ module Cuprum::Collections::Basic
148
126
  end
149
127
  end
150
128
 
151
- def filtered_data
152
- @filtered_data ||=
129
+ def apply_scope(data)
130
+ scope ? scope.call(data:) : data
131
+ end
132
+
133
+ def default_scope
134
+ Cuprum::Collections::Basic::Scopes::AllScope.instance
135
+ end
136
+
137
+ def scoped_data
138
+ @scoped_data ||=
153
139
  data
154
- .then { |ary| apply_filters(ary) }
140
+ .then { |ary| apply_scope(ary) }
155
141
  .then { |ary| apply_order(ary) }
156
142
  .then { |ary| apply_limit_offset(ary) }
157
143
  .map(&:dup)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'cuprum/collections/basic'
4
4
  require 'cuprum/collections/basic/collection'
5
+ require 'cuprum/collections/relations/parameters'
5
6
  require 'cuprum/collections/repository'
6
7
 
7
8
  module Cuprum::Collections::Basic
@@ -21,13 +22,13 @@ module Cuprum::Collections::Basic
21
22
  validate_data!(data)
22
23
 
23
24
  qualified_name =
24
- Cuprum::Collections::Relation::Disambiguation
25
- .resolve_parameters(parameters, name: :collection_name)
25
+ Cuprum::Collections::Relations::Parameters
26
+ .resolve_parameters(parameters)
26
27
  .fetch(:qualified_name)
27
28
 
28
29
  data ||= @data.fetch(qualified_name, [])
29
30
 
30
- Cuprum::Collections::Basic.new(data: data, **parameters)
31
+ Cuprum::Collections::Basic.new(data:, **parameters)
31
32
  end
32
33
 
33
34
  def valid_collection?(collection)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/basic/scopes'
4
+ require 'cuprum/collections/basic/scopes/base'
5
+ require 'cuprum/collections/scopes/all'
6
+
7
+ module Cuprum::Collections::Basic::Scopes
8
+ # Scope for returning unfiltered data.
9
+ class AllScope < Cuprum::Collections::Basic::Scopes::Base
10
+ include Cuprum::Collections::Scopes::All
11
+
12
+ # @return [Cuprum::Collections::Basic::Scopes::AllScope] a cached instance
13
+ # of the all scope.
14
+ def self.instance
15
+ @instance ||= new
16
+ end
17
+
18
+ # Filters the provided data.
19
+ def call(data:)
20
+ raise ArgumentError, 'data must be an Array' unless data.is_a?(Array)
21
+
22
+ data
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/basic/scopes'
4
+ require 'cuprum/collections/scopes/base'
5
+
6
+ module Cuprum::Collections::Basic::Scopes
7
+ # Abstract class representing a set of filters for a basic query.
8
+ class Base < Cuprum::Collections::Scopes::Base
9
+ # Filters the provided data.
10
+ def call(data:)
11
+ raise ArgumentError, 'data must be an Array' unless data.is_a?(Array)
12
+
13
+ data.select { |item| match?(item:) }
14
+ end
15
+
16
+ # Returns true if the provided item matches the scope.
17
+ def match?(item:)
18
+ raise ArgumentError, 'item must be a Hash' unless item.is_a?(Hash)
19
+
20
+ true
21
+ end
22
+ alias matches? match?
23
+
24
+ private
25
+
26
+ def builder
27
+ Cuprum::Collections::Basic::Scopes::Builder.instance
28
+ end
29
+ end
30
+ end
31
+
32
+ require 'cuprum/collections/basic/scopes/builder'
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/basic/scopes'
4
+ require 'cuprum/collections/scopes/building'
5
+
6
+ module Cuprum::Collections::Basic::Scopes
7
+ # Builder for generating Basic collection scopes.
8
+ class Builder
9
+ include Cuprum::Collections::Scopes::Building
10
+
11
+ private
12
+
13
+ def all_scope_class
14
+ Cuprum::Collections::Basic::Scopes::AllScope
15
+ end
16
+
17
+ def conjunction_scope_class
18
+ Cuprum::Collections::Basic::Scopes::ConjunctionScope
19
+ end
20
+
21
+ def criteria_scope_class
22
+ Cuprum::Collections::Basic::Scopes::CriteriaScope
23
+ end
24
+
25
+ def disjunction_scope_class
26
+ Cuprum::Collections::Basic::Scopes::DisjunctionScope
27
+ end
28
+
29
+ def none_scope_class
30
+ Cuprum::Collections::Basic::Scopes::NoneScope
31
+ end
32
+ end
33
+ end
34
+
35
+ require 'cuprum/collections/basic/scopes/all_scope'
36
+ require 'cuprum/collections/basic/scopes/conjunction_scope'
37
+ require 'cuprum/collections/basic/scopes/criteria_scope'
38
+ require 'cuprum/collections/basic/scopes/disjunction_scope'
39
+ require 'cuprum/collections/basic/scopes/none_scope'
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/basic/scopes'
4
+ require 'cuprum/collections/basic/scopes/base'
5
+ require 'cuprum/collections/scopes/conjunction'
6
+
7
+ module Cuprum::Collections::Basic::Scopes
8
+ # Scope for filtering data matching all of the given scopes.
9
+ class ConjunctionScope < Cuprum::Collections::Basic::Scopes::Base
10
+ include Cuprum::Collections::Scopes::Conjunction
11
+
12
+ # Returns true if the provided item matches all of the configured scopes.
13
+ def match?(item:)
14
+ super
15
+
16
+ scopes.all? { |scope| scope.match?(item:) }
17
+ end
18
+ alias matches? match?
19
+ end
20
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/basic/scopes'
4
+ require 'cuprum/collections/basic/scopes/base'
5
+ require 'cuprum/collections/queries'
6
+ require 'cuprum/collections/scopes/criteria'
7
+
8
+ module Cuprum::Collections::Basic::Scopes
9
+ # Scope for filtering on basic collection data based on criteria.
10
+ class CriteriaScope < Cuprum::Collections::Basic::Scopes::Base
11
+ include Cuprum::Collections::Scopes::Criteria
12
+
13
+ Operators = Cuprum::Collections::Queries::Operators
14
+ private_constant :Operators
15
+
16
+ # Returns true if the provided item matches the configured criteria.
17
+ def match?(item:)
18
+ super
19
+
20
+ if inverted?
21
+ criteria.any? do |(attribute, operator, value)|
22
+ filter_for(operator).call(item, attribute, value)
23
+ end
24
+ else
25
+ criteria.all? do |(attribute, operator, value)|
26
+ filter_for(operator).call(item, attribute, value)
27
+ end
28
+ end
29
+ end
30
+ alias matches? match?
31
+
32
+ private
33
+
34
+ def filter_for(operator) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
35
+ case operator
36
+ when Operators::EQUAL
37
+ @eq_filter ||= ->(item, attribute, value) { item[attribute] == value }
38
+ when Operators::GREATER_THAN
39
+ @gt_filter ||= ->(item, attribute, value) { item[attribute] > value }
40
+ when Operators::GREATER_THAN_OR_EQUAL_TO
41
+ @gte_filter ||= ->(item, attribute, value) { item[attribute] >= value }
42
+ when Operators::LESS_THAN
43
+ @lt_filter ||= ->(item, attribute, value) { item[attribute] < value }
44
+ when Operators::LESS_THAN_OR_EQUAL_TO
45
+ @lte_filter ||= ->(item, attribute, value) { item[attribute] <= value }
46
+ when Operators::NOT_EQUAL
47
+ @ne_filter ||= ->(item, attribute, value) { item[attribute] != value }
48
+ when Operators::NOT_ONE_OF
49
+ @nin_filter ||=
50
+ ->(item, attribute, value) { !value.include?(item[attribute]) }
51
+ when Operators::ONE_OF
52
+ @in_filter ||=
53
+ ->(item, attribute, value) { value.include?(item[attribute]) }
54
+ else
55
+ error_class = Cuprum::Collections::Queries::UnknownOperatorException
56
+ message = %(unknown operator "#{operator}")
57
+
58
+ raise error_class.new(message, operator)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/basic/scopes'
4
+ require 'cuprum/collections/basic/scopes/base'
5
+ require 'cuprum/collections/scopes/disjunction'
6
+
7
+ module Cuprum::Collections::Basic::Scopes
8
+ # Scope for filtering data matching any of the given scopes.
9
+ class DisjunctionScope < Cuprum::Collections::Basic::Scopes::Base
10
+ include Cuprum::Collections::Scopes::Disjunction
11
+
12
+ # Returns true if the provided item matches any of the configured scopes.
13
+ def match?(item:)
14
+ super
15
+
16
+ scopes.any? { |scope| scope.match?(item:) }
17
+ end
18
+ alias matches? match?
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/basic/scopes'
4
+ require 'cuprum/collections/basic/scopes/base'
5
+ require 'cuprum/collections/scopes/none'
6
+
7
+ module Cuprum::Collections::Basic::Scopes
8
+ # Scope for returning an empty data set.
9
+ class NoneScope < Cuprum::Collections::Basic::Scopes::Base
10
+ include Cuprum::Collections::Scopes::None
11
+
12
+ # @return [Cuprum::Collections::Basic::Scopes::NoneScope] a cached instance
13
+ # of the none scope.
14
+ def self.instance
15
+ @instance ||= new
16
+ end
17
+
18
+ # Filters the provided data.
19
+ def call(data:)
20
+ raise ArgumentError, 'data must be an Array' unless data.is_a?(Array)
21
+
22
+ []
23
+ end
24
+
25
+ # Returns false for all items.
26
+ def match?(item:)
27
+ super
28
+
29
+ false
30
+ end
31
+ alias matches? match?
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/basic'
4
+
5
+ module Cuprum::Collections::Basic
6
+ # Namespace for basic scope functionality, which filters query data.
7
+ module Scopes
8
+ autoload :AllScope,
9
+ 'cuprum/collections/basic/scopes/all_scope'
10
+ autoload :Base,
11
+ 'cuprum/collections/basic/scopes/base'
12
+ autoload :Builder,
13
+ 'cuprum/collections/basic/scopes/builder'
14
+ autoload :ConjunctionScope,
15
+ 'cuprum/collections/basic/scopes/conjunction_scope'
16
+ autoload :CriteriaScope,
17
+ 'cuprum/collections/basic/scopes/criteria_scope'
18
+ autoload :DisjunctionScope,
19
+ 'cuprum/collections/basic/scopes/disjunction_scope'
20
+ autoload :NoneScope,
21
+ 'cuprum/collections/basic/scopes/none_scope'
22
+ end
23
+ end
@@ -19,5 +19,6 @@ module Cuprum::Collections
19
19
  autoload :Commands, 'cuprum/collections/basic/commands'
20
20
  autoload :Query, 'cuprum/collections/basic/query'
21
21
  autoload :Repository, 'cuprum/collections/basic/repository'
22
+ autoload :Scopes, 'cuprum/collections/basic/scopes'
22
23
  end
23
24
  end