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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a2dd2e704041cbdb689bca94afa13c5803ada5cb0601d7c0870cea1c6740830
4
- data.tar.gz: 0fc7380322c9dbb547354408dbe8fd513ef792c7cb8ee0000aef2b94ef68f921
3
+ metadata.gz: 9a123357ad584d32ba68c2b37f5b8a66b40ff3c17ccd516cdb2cbe9b3a03aa49
4
+ data.tar.gz: b585c2ad781f2fb534bfaccc9999c039519f4a612aaa5c6ad153c4f74fe8f821
5
5
  SHA512:
6
- metadata.gz: 34ed0e5a7d1f528466cc8de3cba741e53143d5defdae69bf1b6daaa5705f715444a92bd0b0b2d8e325c1a6c6ed6c5433760bcb3a6cb357dabf3cd8cf04771311
7
- data.tar.gz: c4ff7c90ce097e3d59e21ac633157358f20571210eee14c4b5b279dc8e16adf05391d6aa1b7205773821775216e859952259f8becf21a054aae24c5d253f90c1
6
+ metadata.gz: 78fd0fe599f33cf43bf2bd31adadd0d5a086e4770593deceed206e6dc990378547cae6d6c1f18e16fecb96e13558793a32af3b32777296c9d0bad0ac1ea1001b
7
+ data.tar.gz: 18aef11051a058e8ed51ebed3263e0280339f279f22485fe5069bc3d5c2830d8bc18b3fab961e2204f2c967f4a12d70ec4f10fb4625f0f634f9c57db8e2e24a9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,78 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ Major refactoring of Queries. This update is **not** backwards compatible.
6
+
7
+ ### Collections
8
+
9
+ Collection commands no longer define the command subclass, e.g. `rockets_collection::Launch`. Instances of the command can still be created using `rockets_collection#launch`.
10
+
11
+ ### Commands
12
+
13
+ Refactored commands to use more lightweight parameter validation from `SleepingKingStudios::Tools`.
14
+
15
+ ### Queries
16
+
17
+ Query result filtering now uses composable scopes.
18
+
19
+ - Implemented `Query#scope`.
20
+ - Implemented composable methods `Query#and`, `Query#or`, `Query#not`.
21
+
22
+ Performing block queries with an implicit receiver is now deprecated. Instead of:
23
+
24
+ `where { { author: eq('J.R.R. Tolkien) } }`
25
+
26
+ An explicit receiver must be passed to be block in order to use operators:
27
+
28
+ `where { |query| { author: query.eq('J.R.R. Tolkien) } }`
29
+
30
+ ### Relations
31
+
32
+ Extracted `Cuprum::Collections::Relations` concerns.
33
+
34
+ - Added `#scope` support to `Cuprum::Collections::Resource`.
35
+
36
+ ### RSpec
37
+
38
+ Migrated shared contract objects to deferred example groups:
39
+
40
+ - `Cuprum::Collections::RSpec::Deferred::AssociationExamples`
41
+ - `Cuprum::Collections::RSpec::Deferred::CollectionExamples`
42
+ - `Cuprum::Collections::RSpec::Deferred::CommandExamples`
43
+ - `Cuprum::Collections::RSpec::Deferred::Commands::*`
44
+ - `Cuprum::Collections::RSpec::Deferred::RelationExamples`
45
+ - `Cuprum::Collections::RSpec::Deferred::ResourceExamples`
46
+
47
+ The corresponding contracts are now deprecated.
48
+
49
+ ### Scopes
50
+
51
+ Implemented `Cuprum::Collections::Scopes`. A scope object represents a filter that can be used to select a subset of a collection.
52
+
53
+ `Cuprum::Collections` defines generic scope classes for defining scopes in a collection-independant fashion. Each collection must also implement the filtering behavior for each scope type.
54
+
55
+ #### Criteria Scopes
56
+
57
+ Criteria scopes use a list of criteria to filter data. Each criterion has an attribute name, an operator (such as "equals", "greater than" or "not in"), and an expected value.
58
+
59
+ #### Logical Scopes
60
+
61
+ Conjunction scopes wrap one or more other scopes with a logical AND operation.
62
+
63
+ Disjunction scopes wrap one or more other scopes with a logical OR operation.
64
+
65
+ #### Scope Inversion
66
+
67
+ Scopes are responsible for defining their own inverse. An inverted scope should match on a collection item if and only if the base scope does not match that item.
68
+
69
+ ### Other Changes
70
+
71
+ Remove deprecations from previous versions:
72
+
73
+ - Removed `Cuprum::Collections::Relation::Disambiguation`.
74
+ - Removed initializing an `AbstractFindError` subclass with `primary_key_name` and `primary_key_values` keywords.
75
+
3
76
  ## 0.4.0
4
77
 
5
78
  ### Associations
data/README.md CHANGED
@@ -26,7 +26,7 @@ The Ruby ecosystem has a wide variety of tools and libraries for managing data a
26
26
 
27
27
  ### Compatibility
28
28
 
29
- Cuprum::Collections is tested against Ruby (MRI) 2.7 through 3.2.
29
+ Cuprum::Collections is tested against Ruby (MRI) 3.1 through 3.4.
30
30
 
31
31
  ### Documentation
32
32
 
@@ -34,7 +34,7 @@ Documentation is generated using [YARD](https://yardoc.org/), and can be generat
34
34
 
35
35
  ### License
36
36
 
37
- Copyright (c) 2020-2023 Rob Smith
37
+ Copyright (c) 2020-2025 Rob Smith
38
38
 
39
39
  Cuprum::Collections is released under the [MIT License](https://opensource.org/licenses/MIT).
40
40
 
@@ -882,11 +882,11 @@ query.each.map(&:author).uniq
882
882
  The simplest way to filter results is by passing a `Hash` to `#where`. The keys of the Hash should be the names of the attributes to filter by, and the values the expected value of that attribute. However, passing a Hash directly only supports equality comparisons. To use advanced operators, use the block form:
883
883
 
884
884
  ```ruby
885
- query = collection.query.where do
885
+ query = collection.query.where do |scope|
886
886
  {
887
887
  author: 'Ursula K. LeGuin',
888
- series: equal('Earthsea'),
889
- published_at: greater_than('1970-01-01')
888
+ series: scope.equal('Earthsea'),
889
+ published_at: scope.greater_than('1970-01-01')
890
890
  }
891
891
  end
892
892
  query.count
@@ -31,33 +31,14 @@ module Cuprum::Collections
31
31
  # @option options singular_inverse_name [String, Symbol] the name of an
32
32
  # entity in the inverse association.
33
33
  def initialize(**params)
34
- params = disambiguate_keyword(params, :entity_class, :association_class)
35
- params = disambiguate_keyword(params, :name, :association_name)
34
+ super(**params.except(:inverse))
36
35
 
37
- @inverse = params.delete(:inverse)
38
-
39
- super(**params)
36
+ @inverse = params[:inverse]
40
37
  end
41
38
 
42
39
  # @return [Cuprum::Collections::Resource] the inverse association, if any.
43
40
  attr_reader :inverse
44
41
 
45
- # @return [Class] the class of entity represented by the resource.
46
- def association_class
47
- tools.core_tools.deprecate '#association_class method',
48
- message: 'Use #entity_class instead'
49
-
50
- entity_class
51
- end
52
-
53
- # @return [String] the name of the resource.
54
- def association_name
55
- tools.core_tools.deprecate '#association_name method',
56
- message: 'Use #name instead'
57
-
58
- name
59
- end
60
-
61
42
  # Generates a query for finding matching items.
62
43
  #
63
44
  # @param entities [Array] the entities to query for.
@@ -71,12 +52,12 @@ module Cuprum::Collections
71
52
  keys =
72
53
  map_entities_to_keys(
73
54
  *entities,
74
- allow_nil: allow_nil,
75
- deduplicate: deduplicate,
55
+ allow_nil:,
56
+ deduplicate:,
76
57
  strict: true
77
58
  )
78
59
 
79
- build_keys_query(*keys, allow_nil: allow_nil, deduplicate: false)
60
+ build_keys_query(*keys, allow_nil:, deduplicate: false)
80
61
  end
81
62
 
82
63
  # Generates a query for finding matching items by key.
@@ -94,11 +75,11 @@ module Cuprum::Collections
94
75
  hash_key = query_key_name
95
76
 
96
77
  if keys.empty?
97
- -> { {} }
78
+ ->(_) { {} }
98
79
  elsif keys.size == 1
99
- -> { { hash_key => keys.first } }
80
+ ->(_) { { hash_key => keys.first } }
100
81
  else
101
- -> { { hash_key => one_of(keys) } }
82
+ ->(scope) { { hash_key => scope.one_of(keys) } }
102
83
  end
103
84
  end
104
85
 
@@ -154,7 +135,7 @@ module Cuprum::Collections
154
135
  )
155
136
  entities
156
137
  .compact
157
- .map { |entity| map_entity_to_key(entity, strict: strict) }
138
+ .map { |entity| map_entity_to_key(entity, strict:) }
158
139
  .then { |keys| allow_nil ? keys : keys.compact }
159
140
  .then { |keys| deduplicate ? keys.uniq : keys }
160
141
  end
@@ -8,10 +8,7 @@ module Cuprum::Collections::Associations
8
8
  class BelongsTo < Cuprum::Collections::Association
9
9
  # (see Cuprum::Collections::Association#initialize)
10
10
  def initialize(**params)
11
- params.delete(:plural)
12
- params.delete(:singular)
13
-
14
- super(**params, singular: true)
11
+ super(**params.except(:plural), singular: true)
15
12
  end
16
13
 
17
14
  # (see Cuprum::Collections::Association#primary_key_query?)
@@ -24,9 +21,5 @@ module Cuprum::Collections::Associations
24
21
  def default_foreign_key_name
25
22
  singular_name&.then { |str| "#{str}_id" }
26
23
  end
27
-
28
- def ignored_parameters
29
- @ignored_parameters ||= Set.new(IGNORED_PARAMETERS + %i[singular])
30
- end
31
24
  end
32
25
  end
@@ -8,16 +8,7 @@ module Cuprum::Collections::Associations
8
8
  class HasMany < Cuprum::Collections::Association
9
9
  # (see Cuprum::Collections::Association#initialize)
10
10
  def initialize(**params)
11
- params.delete(:plural)
12
- params.delete(:singular)
13
-
14
- super(**params, singular: false)
15
- end
16
-
17
- private
18
-
19
- def ignored_parameters
20
- @ignored_parameters ||= Set.new(IGNORED_PARAMETERS + %i[singular])
11
+ super(**params.except(:plural), singular: false)
21
12
  end
22
13
  end
23
14
  end
@@ -8,16 +8,7 @@ module Cuprum::Collections::Associations
8
8
  class HasOne < Cuprum::Collections::Association
9
9
  # (see Cuprum::Collections::Association#initialize)
10
10
  def initialize(**params)
11
- params.delete(:plural)
12
- params.delete(:singular)
13
-
14
- super(**params, singular: true)
15
- end
16
-
17
- private
18
-
19
- def ignored_parameters
20
- @ignored_parameters ||= Set.new(IGNORED_PARAMETERS + %i[singular])
11
+ super(**params.except(:plural), singular: true)
21
12
  end
22
13
  end
23
14
  end
@@ -4,6 +4,7 @@ require 'cuprum/command_factory'
4
4
 
5
5
  require 'cuprum/collections/basic'
6
6
  require 'cuprum/collections/basic/commands'
7
+ require 'cuprum/collections/basic/scopes/all_scope'
7
8
  require 'cuprum/collections/collection'
8
9
 
9
10
  module Cuprum::Collections::Basic
@@ -13,29 +14,20 @@ module Cuprum::Collections::Basic
13
14
  # @param data [Array<Hash>] the current data in the collection.
14
15
  # @param entity_class [Class, String] the class of entity represented by
15
16
  # the relation.
16
- # @param name [String] the name of the relation. Aliased as
17
- # :collection_name.
17
+ # @param name [String] the name of the relation.
18
18
  # @param qualified_name [String] a scoped name for the relation.
19
19
  # @param singular_name [String] the name of an entity in the relation.
20
- # Aliased as :member_name.
21
20
  # @param options [Hash] additional options for the relation.
22
21
  #
23
22
  # @option options primary_key_name [String] the name of the primary key
24
23
  # attribute. Defaults to 'id'.
25
- # @option primary_key_type [Class, Stannum::Constraint] the type of
26
- # the primary key attribute. Defaults to Integer.
27
- def initialize(data: [], entity_class: Hash, **parameters)
28
- qualified_name = parameters.fetch(:qualified_name) do
29
- next nil unless entity_class == Hash
30
-
31
- parameters.fetch(:collection_name, parameters[:name])
32
- end
33
-
34
- super(
35
- entity_class: entity_class,
36
- qualified_name: qualified_name,
37
- **parameters
38
- )
24
+ # @option options primary_key_type [Class, Stannum::Constraint] the type
25
+ # of the primary key attribute. Defaults to Integer.
26
+ # @option options scope
27
+ # [Cuprum::Collections::Scopes::Base, Hash, Proc, nil] the configured
28
+ # scope for the relation.
29
+ def initialize(data: [], **parameters)
30
+ super(**normalize_parameters(**parameters))
39
31
 
40
32
  @data = data
41
33
  end
@@ -43,49 +35,40 @@ module Cuprum::Collections::Basic
43
35
  # @return [Array<Hash>] the current data in the collection.
44
36
  attr_reader :data
45
37
 
46
- command_class :assign_one do
47
- Cuprum::Collections::Basic::Commands::AssignOne
48
- .subclass(**command_options)
38
+ command :assign_one do
39
+ Cuprum::Collections::Basic::Commands::AssignOne.new(collection: self)
49
40
  end
50
41
 
51
- command_class :build_one do
52
- Cuprum::Collections::Basic::Commands::BuildOne
53
- .subclass(**command_options)
42
+ command :build_one do
43
+ Cuprum::Collections::Basic::Commands::BuildOne.new(collection: self)
54
44
  end
55
45
 
56
- command_class :destroy_one do
57
- Cuprum::Collections::Basic::Commands::DestroyOne
58
- .subclass(**command_options)
46
+ command :destroy_one do
47
+ Cuprum::Collections::Basic::Commands::DestroyOne.new(collection: self)
59
48
  end
60
49
 
61
- command_class :find_many do
62
- Cuprum::Collections::Basic::Commands::FindMany
63
- .subclass(**command_options)
50
+ command :find_many do
51
+ Cuprum::Collections::Basic::Commands::FindMany.new(collection: self)
64
52
  end
65
53
 
66
- command_class :find_matching do
67
- Cuprum::Collections::Basic::Commands::FindMatching
68
- .subclass(**command_options)
54
+ command :find_matching do
55
+ Cuprum::Collections::Basic::Commands::FindMatching.new(collection: self)
69
56
  end
70
57
 
71
- command_class :find_one do
72
- Cuprum::Collections::Basic::Commands::FindOne
73
- .subclass(**command_options)
58
+ command :find_one do
59
+ Cuprum::Collections::Basic::Commands::FindOne.new(collection: self)
74
60
  end
75
61
 
76
- command_class :insert_one do
77
- Cuprum::Collections::Basic::Commands::InsertOne
78
- .subclass(**command_options)
62
+ command :insert_one do
63
+ Cuprum::Collections::Basic::Commands::InsertOne.new(collection: self)
79
64
  end
80
65
 
81
- command_class :update_one do
82
- Cuprum::Collections::Basic::Commands::UpdateOne
83
- .subclass(**command_options)
66
+ command :update_one do
67
+ Cuprum::Collections::Basic::Commands::UpdateOne.new(collection: self)
84
68
  end
85
69
 
86
- command_class :validate_one do
87
- Cuprum::Collections::Basic::Commands::ValidateOne
88
- .subclass(**command_options)
70
+ command :validate_one do
71
+ Cuprum::Collections::Basic::Commands::ValidateOne.new(collection: self)
89
72
  end
90
73
 
91
74
  # @return [Stannum::Constraints::Base, nil] the # default contract for
@@ -98,16 +81,40 @@ module Cuprum::Collections::Basic
98
81
  #
99
82
  # @return [Cuprum::Collections::Basic::Query] the query.
100
83
  def query
101
- Cuprum::Collections::Basic::Query.new(data)
84
+ Cuprum::Collections::Basic::Query.new(data, scope:)
102
85
  end
103
86
 
104
87
  protected
105
88
 
106
- def command_options
107
- super().merge(
108
- data: data,
109
- default_contract: default_contract
89
+ def comparable_options
90
+ @comparable_options ||= super.merge(
91
+ data:,
92
+ default_contract:
110
93
  )
111
94
  end
95
+
96
+ private
97
+
98
+ def default_scope
99
+ Cuprum::Collections::Basic::Scopes::AllScope.new
100
+ end
101
+
102
+ def normalize_parameters(**parameters) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
103
+ return parameters if parameters.key?(:entity_class)
104
+
105
+ return parameters unless parameters[:name] || parameters[:qualified_name]
106
+
107
+ parameters = parameters.merge(entity_class: Hash)
108
+
109
+ if parameters.key?(:name) && parameters.key?(:qualified_name)
110
+ parameters
111
+ elsif parameters.key?(:name)
112
+ parameters.merge(qualified_name: parameters[:name])
113
+ elsif parameters.key?(:qualified_name)
114
+ name = parameters[:qualified_name].split('/').last
115
+
116
+ parameters.merge(name:)
117
+ end
118
+ end
112
119
  end
113
120
  end
@@ -6,107 +6,41 @@ require 'cuprum/collections/basic'
6
6
 
7
7
  module Cuprum::Collections::Basic
8
8
  # Abstract base class for basic collection commands.
9
- class Command < Cuprum::Collections::Command
10
- # Creates a subclass with the given parameters applied to the constructor.
11
- def self.subclass(**default_options)
12
- Class.new(self) do
13
- define_method(:initialize) do |**options|
14
- super(**default_options.merge(options))
15
- end
16
- end
17
- end
18
-
19
- # @param collection_name [String, Symbol] The name of the collection.
20
- # @param data [Array<Hash>] The current data in the collection.
21
- # @param default_contract [Stannum::Constraints::Base, nil] The default
22
- # contract for validating items in the collection.
23
- # @param member_name [String] The name of a collection entity.
24
- # @param primary_key_name [Symbol] The name of the primary key attribute.
25
- # Defaults to :id.
26
- # @param primary_key_type [Class, Stannum::Constraint] The type of the
27
- # primary key attribute. Defaults to Integer.
28
- # @param options [Hash<Symbol>] Additional options for the command.
29
- def initialize( # rubocop:disable Metrics/ParameterLists
30
- collection_name:,
31
- data:,
32
- default_contract: nil,
33
- member_name: nil,
34
- primary_key_name: :id,
35
- primary_key_type: Integer,
36
- **options
37
- )
38
- super()
39
-
40
- @collection_name = collection_name.to_s
41
- @data = data
42
- @default_contract = default_contract
43
- @member_name =
44
- member_name ? member_name.to_s : tools.str.singularize(@collection_name)
45
- @options = options
46
- @primary_key_name = primary_key_name
47
- @primary_key_type = primary_key_type
48
- end
49
-
50
- # @return [String] the name of the collection.
51
- attr_reader :collection_name
52
-
9
+ class Command < Cuprum::Collections::CollectionCommand
53
10
  # @return [Array<Hash>] the current data in the collection.
54
- attr_reader :data
11
+ def data
12
+ collection.data
13
+ end
55
14
 
56
15
  # @return [Stannum::Constraints::Base, nil] the default contract for
57
16
  # validating items in the collection.
58
- attr_reader :default_contract
59
-
60
- # @return [String] the name of a collection entity.
61
- attr_reader :member_name
62
-
63
- # @return [Hash<Symbol>] additional options for the command.
64
- attr_reader :options
65
-
66
- # @return [Symbol] the name of the primary key attribute.
67
- attr_reader :primary_key_name
68
-
69
- # @return [Class, Stannum::Constraint] the type of the primary key
70
- # attribute.
71
- attr_reader :primary_key_type
17
+ def default_contract
18
+ @default_contract ||= collection.default_contract
19
+ end
72
20
 
73
21
  private
74
22
 
75
- def primary_key_contract
76
- type = primary_key_type
23
+ def validate_entity(value, as: 'entity') # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
24
+ return error_message_for(as:, expected: Hash) unless value.is_a?(Hash)
77
25
 
78
- @primary_key_contract ||= Stannum::Contracts::ParametersContract.new do
79
- keyword :primary_key, type
80
- end
81
- end
26
+ return [] if value.empty?
82
27
 
83
- def primary_keys_contract
84
- type = primary_key_type
28
+ validator = tools.assertions.aggregator_class.new
85
29
 
86
- @primary_keys_contract ||= Stannum::Contracts::ParametersContract.new do
87
- keyword :primary_keys,
88
- Stannum::Constraints::Types::ArrayType.new(item_type: type)
89
- end
90
- end
30
+ value.each_key do |key|
31
+ unless key.nil? || key.is_a?(String)
32
+ validator << error_message_for(
33
+ as: "#{as}[#{key.inspect}] key",
34
+ expected: String
35
+ )
91
36
 
92
- def tools
93
- SleepingKingStudios::Tools::Toolbelt.instance
94
- end
37
+ next
38
+ end
95
39
 
96
- def validate_primary_key(primary_key)
97
- match_parameters_to_contract(
98
- contract: primary_key_contract,
99
- keywords: { primary_key: primary_key },
100
- method_name: :call
101
- )
102
- end
40
+ validator.validate_presence(key, as: "#{as}[#{key.inspect}] key")
41
+ end
103
42
 
104
- def validate_primary_keys(primary_keys)
105
- match_parameters_to_contract(
106
- contract: primary_keys_contract,
107
- keywords: { primary_keys: primary_keys },
108
- method_name: :call
109
- )
43
+ validator.each.to_a
110
44
  end
111
45
  end
112
46
  end
@@ -36,12 +36,8 @@ module Cuprum::Collections::Basic::Commands
36
36
  # 'series' => nil,
37
37
  # 'category' => 'Science Fiction and Fantasy'
38
38
  # }
39
- validate_parameters :call do
40
- keyword :attributes,
41
- Stannum::Constraints::Types::HashWithIndifferentKeys.new
42
- keyword :entity,
43
- Stannum::Constraints::Types::HashWithStringKeys.new
44
- end
39
+ validate :attributes
40
+ validate :entity
45
41
 
46
42
  private
47
43
 
@@ -31,10 +31,7 @@ module Cuprum::Collections::Basic::Commands
31
31
  # 'series' => nil,
32
32
  # 'category' => 'Science Fiction and Fantasy'
33
33
  # }
34
- validate_parameters :call do
35
- keyword :attributes,
36
- Stannum::Constraints::Types::HashWithIndifferentKeys.new
37
- end
34
+ validate :attributes
38
35
 
39
36
  private
40
37
 
@@ -18,9 +18,7 @@ module Cuprum::Collections::Basic::Commands
18
18
  #
19
19
  # @return [Cuprum::Result<Hash{String, Object}>] a result with the
20
20
  # destroyed item.
21
- validate_parameters :call do
22
- keyword :primary_key, Object
23
- end
21
+ validate :primary_key
24
22
 
25
23
  private
26
24
 
@@ -30,18 +28,16 @@ module Cuprum::Collections::Basic::Commands
30
28
  error = Cuprum::Collections::Errors::NotFound.new(
31
29
  attribute_name: primary_key_name,
32
30
  attribute_value: primary_key,
33
- collection_name: collection_name,
31
+ collection_name:,
34
32
  primary_key: true
35
33
  )
36
- Cuprum::Result.new(error: error)
34
+ Cuprum::Result.new(error:)
37
35
  end
38
36
 
39
37
  def process(primary_key:)
40
- step { validate_primary_key(primary_key) }
41
-
42
38
  index = data.index { |item| item[primary_key_name.to_s] == primary_key }
43
39
 
44
- step { handle_missing_item(index: index, primary_key: primary_key) }
40
+ step { handle_missing_item(index:, primary_key:) }
45
41
 
46
42
  data.delete_at(index)
47
43
  end
@@ -11,7 +11,7 @@ module Cuprum::Collections::Basic::Commands
11
11
  class FindMany < Cuprum::Collections::Basic::Command
12
12
  include Cuprum::Collections::Commands::AbstractFindMany
13
13
 
14
- # @!method call(primary_keys:, allow_partial: false, envelope: false, scope: nil)
14
+ # @!method call(primary_keys:, allow_partial: false, envelope: false)
15
15
  # Queries the collection for the items with the given primary keys.
16
16
  #
17
17
  # The command will find and return the entities with the given primary
@@ -27,39 +27,19 @@ module Cuprum::Collections::Basic::Commands
27
27
  # found.
28
28
  # @param envelope [Boolean] If true, wraps the result value in a Hash.
29
29
  # @param primary_keys [Array] The primary keys of the requested items.
30
- # @param scope [Cuprum::Collections::Basic::Query, nil] Optional scope for
31
- # the query. Items must match the scope as well as the primary keys.
32
30
  #
33
31
  # @return [Cuprum::Result<Array<Hash{String, Object}>>] a result with the
34
32
  # requested items.
35
- validate_parameters :call do
36
- keyword :allow_partial, Stannum::Constraints::Boolean.new, default: true
37
- keyword :envelope, Stannum::Constraints::Boolean.new, default: true
38
- keyword :primary_keys, Array
39
- keyword :scope, Cuprum::Collections::Basic::Query, optional: true
40
- end
33
+ validate :allow_partial, :boolean, optional: true
34
+ validate :envelope, :boolean, optional: true
35
+ validate :primary_keys
41
36
 
42
37
  private
43
38
 
44
- def build_query
45
- Cuprum::Collections::Basic::Query.new(data)
46
- end
47
-
48
39
  def items_with_primary_keys(items:)
49
40
  # :nocov:
50
41
  items.to_h { |item| [item[primary_key_name.to_s], item] }
51
42
  # :nocov:
52
43
  end
53
-
54
- def process(
55
- primary_keys:,
56
- allow_partial: false,
57
- envelope: false,
58
- scope: nil
59
- )
60
- step { validate_primary_keys(primary_keys) }
61
-
62
- super
63
- end
64
44
  end
65
45
  end