cuprum-collections 0.3.0 → 0.4.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +48 -0
  3. data/DEVELOPMENT.md +2 -2
  4. data/README.md +13 -11
  5. data/lib/cuprum/collections/association.rb +256 -0
  6. data/lib/cuprum/collections/associations/belongs_to.rb +32 -0
  7. data/lib/cuprum/collections/associations/has_many.rb +23 -0
  8. data/lib/cuprum/collections/associations/has_one.rb +23 -0
  9. data/lib/cuprum/collections/associations.rb +10 -0
  10. data/lib/cuprum/collections/basic/collection.rb +39 -74
  11. data/lib/cuprum/collections/basic/commands/find_many.rb +1 -1
  12. data/lib/cuprum/collections/basic/commands/find_matching.rb +1 -1
  13. data/lib/cuprum/collections/basic/repository.rb +9 -33
  14. data/lib/cuprum/collections/basic.rb +1 -0
  15. data/lib/cuprum/collections/collection.rb +154 -0
  16. data/lib/cuprum/collections/commands/associations/find_many.rb +161 -0
  17. data/lib/cuprum/collections/commands/associations/require_many.rb +48 -0
  18. data/lib/cuprum/collections/commands/associations.rb +13 -0
  19. data/lib/cuprum/collections/commands/find_one_matching.rb +1 -1
  20. data/lib/cuprum/collections/commands.rb +1 -0
  21. data/lib/cuprum/collections/errors/abstract_find_error.rb +1 -1
  22. data/lib/cuprum/collections/relation.rb +401 -0
  23. data/lib/cuprum/collections/repository.rb +71 -4
  24. data/lib/cuprum/collections/resource.rb +65 -0
  25. data/lib/cuprum/collections/rspec/contracts/association_contracts.rb +2137 -0
  26. data/lib/cuprum/collections/rspec/contracts/basic/command_contracts.rb +484 -0
  27. data/lib/cuprum/collections/rspec/contracts/basic.rb +11 -0
  28. data/lib/cuprum/collections/rspec/contracts/collection_contracts.rb +429 -0
  29. data/lib/cuprum/collections/rspec/contracts/command_contracts.rb +1462 -0
  30. data/lib/cuprum/collections/rspec/contracts/query_contracts.rb +1093 -0
  31. data/lib/cuprum/collections/rspec/contracts/relation_contracts.rb +1381 -0
  32. data/lib/cuprum/collections/rspec/contracts/repository_contracts.rb +605 -0
  33. data/lib/cuprum/collections/rspec/contracts.rb +23 -0
  34. data/lib/cuprum/collections/rspec/fixtures.rb +85 -82
  35. data/lib/cuprum/collections/rspec.rb +4 -1
  36. data/lib/cuprum/collections/version.rb +1 -1
  37. data/lib/cuprum/collections.rb +9 -4
  38. metadata +23 -19
  39. data/lib/cuprum/collections/base.rb +0 -11
  40. data/lib/cuprum/collections/basic/rspec/command_contract.rb +0 -392
  41. data/lib/cuprum/collections/rspec/assign_one_command_contract.rb +0 -168
  42. data/lib/cuprum/collections/rspec/build_one_command_contract.rb +0 -93
  43. data/lib/cuprum/collections/rspec/collection_contract.rb +0 -190
  44. data/lib/cuprum/collections/rspec/destroy_one_command_contract.rb +0 -108
  45. data/lib/cuprum/collections/rspec/find_many_command_contract.rb +0 -407
  46. data/lib/cuprum/collections/rspec/find_matching_command_contract.rb +0 -194
  47. data/lib/cuprum/collections/rspec/find_one_command_contract.rb +0 -157
  48. data/lib/cuprum/collections/rspec/insert_one_command_contract.rb +0 -84
  49. data/lib/cuprum/collections/rspec/query_builder_contract.rb +0 -92
  50. data/lib/cuprum/collections/rspec/query_contract.rb +0 -650
  51. data/lib/cuprum/collections/rspec/querying_contract.rb +0 -298
  52. data/lib/cuprum/collections/rspec/repository_contract.rb +0 -235
  53. data/lib/cuprum/collections/rspec/update_one_command_contract.rb +0 -80
  54. data/lib/cuprum/collections/rspec/validate_one_command_contract.rb +0 -96
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dda6613af3def3463515616a0b448dce3ce0fb666b6b81b9c9d54cf9e4f6bef0
4
- data.tar.gz: e8cae0cd8e96daf887268b0b467352d34a7a93357729c14115375f7d14d2e2d8
3
+ metadata.gz: 9a2dd2e704041cbdb689bca94afa13c5803ada5cb0601d7c0870cea1c6740830
4
+ data.tar.gz: 0fc7380322c9dbb547354408dbe8fd513ef792c7cb8ee0000aef2b94ef68f921
5
5
  SHA512:
6
- metadata.gz: 138cf1bd095d6d03e196c90ac4779ee6d8dec8743f8cb321c4114117c707ef0124f378642653beef0e3db1c0d127cebd05967a4356ce5361cd3294bd298642e7
7
- data.tar.gz: 968b185b8e1b0447b55acc093387ad527e0ba5154b0e4a24d2ace52cf258ca29939eefa0cc772451703d1b56286dce907c84402a735a360152d3573ea8cb5db7
6
+ metadata.gz: 34ed0e5a7d1f528466cc8de3cba741e53143d5defdae69bf1b6daaa5705f715444a92bd0b0b2d8e325c1a6c6ed6c5433760bcb3a6cb357dabf3cd8cf04771311
7
+ data.tar.gz: c4ff7c90ce097e3d59e21ac633157358f20571210eee14c4b5b279dc8e16adf05391d6aa1b7205773821775216e859952259f8becf21a054aae24c5d253f90c1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Associations
6
+
7
+ Implemented `Cuprum::Collections::Association`, which represents an association between entity types.
8
+
9
+ - Implemented `Cuprum::Collections::Associations::BelongsTo`.
10
+ - Implemented `Cuprum::Collections::Associations::HasMany`.
11
+ - Implemented `Cuprum::Collections::Associations::HasOne`.
12
+
13
+ ### Collections
14
+
15
+ Defined standard interface for collections.
16
+
17
+ - Implemented `Cuprum::Collections::Collection`.
18
+ - Collections can now be initialized with any combination of collection name, entity class, and qualified name.
19
+
20
+ Deprecated certain collection methods and corresponding constructor keywords:
21
+
22
+ - `#collection_name`: Use `#name`.
23
+ - `#member_name`: Use `#singular_name`.
24
+
25
+ ### Commands
26
+
27
+ Implemented association Commands, which find or require association entities from a list of entities or keys.
28
+
29
+ - `Commands::Associations::FindMany`
30
+ - `Commands::Associations::RequireMany`
31
+
32
+ ### Relations
33
+
34
+ Defined `Cuprum::Collections::Relation`, an abstract class representing a group or view of entities.
35
+
36
+ ### Repositories
37
+
38
+ Defined standard interface for repositories.
39
+
40
+ - Implemented `Repository#create`.
41
+ - Implemented `Repository#find_or_create`.
42
+
43
+ ### Resources
44
+
45
+ Defined `Cuprum::Collections::Resource`, representing a singular or plural resource of entities.
46
+
47
+ ### RSpec
48
+
49
+ - **(Breaking Change)** Contracts have been refactored to use `RSpec::SleepingKingStudios::Contract`. Contract names and filenames have changed.
50
+
3
51
  ## 0.3.0
4
52
 
5
53
  ### Collections
data/DEVELOPMENT.md CHANGED
@@ -8,8 +8,8 @@ Steps to add an operator:
8
8
 
9
9
  - Update Queries::Operators.
10
10
  - Update Queries::ParseBlock::Builder.
11
- - Define context(s) in RSpec::QUERYING_CONTEXTS.
12
- - Add test cases in RSpec::QUERYING_CONTRACT.
11
+ - Define context(s) in QueryContracts::WithQueryContexts.
12
+ - Add test cases in QueryContracts::ShouldPerformQueries.
13
13
  - Add implementations to Basic::QueryBuilder.
14
14
 
15
15
  ### ParseCriteria
data/README.md CHANGED
@@ -68,8 +68,8 @@ Each collection provides three features:
68
68
 
69
69
  ```ruby
70
70
  collection = Cuprum::Collections::Basic.new(
71
- collection_name: 'books',
72
- data: book_data,
71
+ name: 'books',
72
+ data: book_data,
73
73
  )
74
74
 
75
75
  # Add an item to the collection.
@@ -107,10 +107,12 @@ Because a collection can represent any sort of data, from a raw Ruby Hash to an
107
107
 
108
108
  Each collection also defines the following methods:
109
109
 
110
- - `#collection_name`: The collection name is a short description of what the collection contains. For example, a collection of `Book` objects might have a collection name of `'books'`, while a collection of `Authorization::Credentials::ApiKey` objects might have a collection name of `'api_keys'`.
110
+ - `#name`: The collection name is a short description of what the collection contains. For example, a collection of `Book` objects might have a collection name of `'books'`, while a collection of `Authorization::Credentials::ApiKey` objects might have a collection name of `'api_keys'`.
111
+ - `#entity_class`: The type of entity contained in the collection.
111
112
  - `#qualified_name`: The qualified name is a full description of the collection, and should be unique. For example, a collection of `Book` objects might have a qualified name of `'books'`, while a collection of `Authorization::Credentials::ApiKey` objects might have a qualified name of `'authorization/credentials/api_keys'`.
113
+ - `#singular_name`: The name of an item in the collection.
112
114
 
113
- As a general rule, the `#collection_name` is used when displaying information to the user, while the `#qualified_name` is used to uniquely identify the collection (such as when adding to or retrieving from a [Repository](#repositories)).
115
+ As a general rule, the `#name` is used when displaying information to the user, while the `#qualified_name` is used to uniquely identify the collection (such as when adding to or retrieving from a [Repository](#repositories)).
114
116
 
115
117
  <a id="commands"></a>
116
118
 
@@ -406,7 +408,7 @@ repository.key?('api_keys')
406
408
  repository.key?('authorization/credentials/api_keys')
407
409
  #=> false
408
410
 
409
- api_keys_collection.collection_name
411
+ api_keys_collection.name
410
412
  #=> 'api_keys'
411
413
  api_keys_collection.qualified_name
412
414
  #=> 'authorization/credentials/api_keys'
@@ -432,14 +434,14 @@ The `Cuprum::Basic::Collection` provides a reference implementation of a collect
432
434
 
433
435
  ```ruby
434
436
  collection = Cuprum::Collections::Basic.new(
435
- collection_name: 'books',
436
- data: book_data,
437
+ name: 'books',
438
+ data: book_data,
437
439
  )
438
440
  ```
439
441
 
440
442
  Initializing a basic collection requires, at a minumum, the following keywords:
441
443
 
442
- - The `:collection_name` parameter sets the name of the collection. It is used to create an envelope for query commands, such as the `FindMany`, `FindMatching` and `FindOne` commands.
444
+ - The `:name` parameter sets the name of the collection. It is used to create an envelope for query commands, such as the `FindMany`, `FindMatching` and `FindOne` commands.
443
445
  - The `:data` parameter initializes the collection with existing data. The data must be either an empty array or an `Array` of `Hash`es with `String` keys.
444
446
 
445
447
  You can also specify some optional keywords:
@@ -471,7 +473,7 @@ repository = Cuprum::Collections::Basic::Repository.new(data: data)
471
473
  repository.keys
472
474
  #=> []
473
475
 
474
- repository.build(collection_name: 'books')
476
+ repository.build(name: 'books')
475
477
  #=> an instance of Cuprum::Collections::Basic::Collection
476
478
  repository.keys
477
479
  #=> ['books']
@@ -593,8 +595,8 @@ A `Cuprum::Collections::Query` provides a low-level interface for performing que
593
595
 
594
596
  ```ruby
595
597
  collection = Cuprum::Collections::Basic.new(
596
- collection_name: 'books',
597
- data: book_data,
598
+ name: 'books',
599
+ data: book_data,
598
600
  )
599
601
  query = collection.query
600
602
 
@@ -0,0 +1,256 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections'
4
+ require 'cuprum/collections/resource'
5
+
6
+ module Cuprum::Collections
7
+ # Class representing an association between resources.
8
+ class Association < Resource # rubocop:disable Metrics/ClassLength
9
+ # @overload initialize(entity_class: nil, name: nil, qualified_name: nil, singular_name: nil, **options)
10
+ # @param entity_class [Class, String] the class of entity represented by
11
+ # the resource.
12
+ # @param inverse [Cuprum::Collections::Resource] the inverse association,
13
+ # if any.
14
+ # @param name [String] the name of the resource.
15
+ # @param qualified_name [String] a scoped name for the resource.
16
+ # @param singular_name [String] the name of an entity in the resource.
17
+ # @param options [Hash] additional options for the resource.
18
+ #
19
+ # @option options foreign_key_name [String] the name of the foreign key
20
+ # attribute.
21
+ # @option options inverse_class [Class, String] the class of the inverse
22
+ # association.
23
+ # @option options inverse_name [String, Symbol] the name of the inverse
24
+ # association.
25
+ # @option options plural [Boolean] if true, the resource represents a
26
+ # plural resource. Defaults to true. Can also be specified as :singular.
27
+ # @option options primary_key_name [String] the name of the primary key
28
+ # attribute. Defaults to 'id'.
29
+ # @option primary_key_type [Class, Stannum::Constraint] the type of
30
+ # the primary key attribute. Defaults to Integer.
31
+ # @option options singular_inverse_name [String, Symbol] the name of an
32
+ # entity in the inverse association.
33
+ def initialize(**params)
34
+ params = disambiguate_keyword(params, :entity_class, :association_class)
35
+ params = disambiguate_keyword(params, :name, :association_name)
36
+
37
+ @inverse = params.delete(:inverse)
38
+
39
+ super(**params)
40
+ end
41
+
42
+ # @return [Cuprum::Collections::Resource] the inverse association, if any.
43
+ attr_reader :inverse
44
+
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
+ # Generates a query for finding matching items.
62
+ #
63
+ # @param entities [Array] the entities to query for.
64
+ # @param allow_nil [Boolean] if true, allows for nil keys. Defaults to
65
+ # false.
66
+ # @param deduplicate [Boolean] if true, removes duplicate keys before
67
+ # generating the query. Defaults to true.
68
+ #
69
+ # @return [Proc] the generated query.
70
+ def build_entities_query(*entities, allow_nil: false, deduplicate: true)
71
+ keys =
72
+ map_entities_to_keys(
73
+ *entities,
74
+ allow_nil: allow_nil,
75
+ deduplicate: deduplicate,
76
+ strict: true
77
+ )
78
+
79
+ build_keys_query(*keys, allow_nil: allow_nil, deduplicate: false)
80
+ end
81
+
82
+ # Generates a query for finding matching items by key.
83
+ #
84
+ # @param keys [Array] the primary or foreign keys to query for.
85
+ # @param allow_nil [Boolean] if true, allows for nil keys. Defaults to
86
+ # false.
87
+ # @param deduplicate [Boolean] if true, removes duplicate keys before
88
+ # generating the query. Defaults to true.
89
+ #
90
+ # @return [Proc] the generated query.
91
+ def build_keys_query(*keys, allow_nil: false, deduplicate: true)
92
+ keys = keys.compact unless allow_nil
93
+ keys = keys.uniq if deduplicate
94
+ hash_key = query_key_name
95
+
96
+ if keys.empty?
97
+ -> { {} }
98
+ elsif keys.size == 1
99
+ -> { { hash_key => keys.first } }
100
+ else
101
+ -> { { hash_key => one_of(keys) } }
102
+ end
103
+ end
104
+
105
+ # @return [String] the name of the foreign key attribute.
106
+ def foreign_key_name
107
+ @foreign_key_name ||=
108
+ options
109
+ .fetch(:foreign_key_name) { default_foreign_key_name }
110
+ &.to_s
111
+ end
112
+
113
+ # @return [Class] the class of the inverse association, if any.
114
+ def inverse_class
115
+ @inverse_class ||=
116
+ options
117
+ .fetch(:inverse_class) { inverse&.entity_class }
118
+ .then do |value|
119
+ value.is_a?(String) ? Object.const_get(value) : value
120
+ end
121
+ end
122
+
123
+ # @return [String] the name of the inverse key.
124
+ def inverse_key_name
125
+ return foreign_key_name if primary_key_query?
126
+
127
+ primary_key_name
128
+ end
129
+
130
+ # @return [String] the name of the inverse association, if any.
131
+ def inverse_name
132
+ @inverse_name ||=
133
+ options
134
+ .fetch(:inverse_name) { default_inverse_name }
135
+ &.to_s
136
+ end
137
+
138
+ # Maps a list of entities to keys for performing a query.
139
+ #
140
+ # @param entities [Array] the entities to query for.
141
+ # @param allow_nil [Boolean] if true, allows for nil keys. Defaults to
142
+ # false.
143
+ # @param deduplicate [Boolean] if true, removes duplicate keys before
144
+ # generating the query. Defaults to true.
145
+ # @param strict [Boolean] if true, raises an exception if given an Array of
146
+ # keys instead of entities.
147
+ #
148
+ # @return [Array] the primary or foreign keys to query for.
149
+ def map_entities_to_keys(
150
+ *entities,
151
+ allow_nil: false,
152
+ deduplicate: true,
153
+ strict: true
154
+ )
155
+ entities
156
+ .compact
157
+ .map { |entity| map_entity_to_key(entity, strict: strict) }
158
+ .then { |keys| allow_nil ? keys : keys.compact }
159
+ .then { |keys| deduplicate ? keys.uniq : keys }
160
+ end
161
+
162
+ # @return [Boolean] true if the association queries by primary key, e.g. a
163
+ # :belongs_to association; false if the association queries by foreign
164
+ # key, e.g. a :has_one or :has_many association.
165
+ def primary_key_query?
166
+ false
167
+ end
168
+
169
+ # @return [String] the name of the key used to perform the query.
170
+ def query_key_name
171
+ return primary_key_name if primary_key_query?
172
+
173
+ if foreign_key_name.nil? || foreign_key_name.empty?
174
+ raise ArgumentError, "foreign key name can't be blank"
175
+ end
176
+
177
+ foreign_key_name
178
+ end
179
+
180
+ # @return [String] the name of an entity in the inverse association.
181
+ def singular_inverse_name
182
+ @singular_inverse_name ||=
183
+ options
184
+ .fetch(:singular_inverse_name) { default_singular_inverse_name }
185
+ &.to_s
186
+ end
187
+
188
+ # Creates a copy of the association with the specified inverse association.
189
+ #
190
+ # @param inverse [Cuprum::Collections::Resource] the inverse association.
191
+ #
192
+ # @return [Cuprum::Collections::Association] the copied association.
193
+ def with_inverse(inverse)
194
+ dup.assign_inverse(inverse)
195
+ end
196
+
197
+ protected
198
+
199
+ def assign_inverse(inverse)
200
+ @inverse = inverse
201
+ @inverse_class = nil
202
+ @inverse_name = nil
203
+ @foreign_key_name = nil
204
+ @singular_inverse_name = nil
205
+
206
+ self
207
+ end
208
+
209
+ private
210
+
211
+ def default_foreign_key_name
212
+ singular_inverse_name&.then { |str| "#{str}_id" }
213
+ end
214
+
215
+ def default_inverse_name
216
+ inverse&.name
217
+ end
218
+
219
+ def default_singular_inverse_name
220
+ return inverse.singular_name if inverse
221
+
222
+ return tools.string_tools.singularize(inverse_name) if inverse_name
223
+
224
+ nil
225
+ end
226
+
227
+ def entity_key_name
228
+ primary_key_query? ? foreign_key_name : primary_key_name
229
+ end
230
+
231
+ def indexed?(value)
232
+ return false if value.is_a?(Integer)
233
+
234
+ return false if value.is_a?(String)
235
+
236
+ value.respond_to?(:[])
237
+ end
238
+
239
+ def map_entity_to_key(value, strict: false)
240
+ key = entity_key_name
241
+
242
+ return value[key] if indexed?(value)
243
+
244
+ return value.send(key) if value.respond_to?(key)
245
+
246
+ return value if !strict && value.is_a?(primary_key_type)
247
+
248
+ raise ArgumentError,
249
+ "undefined method :[] or :#{key} for #{value.inspect}"
250
+ end
251
+
252
+ def tools
253
+ SleepingKingStudios::Tools::Toolbelt.instance
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/association'
4
+ require 'cuprum/collections/associations'
5
+
6
+ module Cuprum::Collections::Associations
7
+ # Object representing a belongs_to association, which inverts the foreign key.
8
+ class BelongsTo < Cuprum::Collections::Association
9
+ # (see Cuprum::Collections::Association#initialize)
10
+ def initialize(**params)
11
+ params.delete(:plural)
12
+ params.delete(:singular)
13
+
14
+ super(**params, singular: true)
15
+ end
16
+
17
+ # (see Cuprum::Collections::Association#primary_key_query?)
18
+ def primary_key_query?
19
+ true
20
+ end
21
+
22
+ private
23
+
24
+ def default_foreign_key_name
25
+ singular_name&.then { |str| "#{str}_id" }
26
+ end
27
+
28
+ def ignored_parameters
29
+ @ignored_parameters ||= Set.new(IGNORED_PARAMETERS + %i[singular])
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/association'
4
+ require 'cuprum/collections/associations'
5
+
6
+ module Cuprum::Collections::Associations
7
+ # Object representing a has_many association.
8
+ class HasMany < Cuprum::Collections::Association
9
+ # (see Cuprum::Collections::Association#initialize)
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])
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections/association'
4
+ require 'cuprum/collections/associations'
5
+
6
+ module Cuprum::Collections::Associations
7
+ # Object representing a has_one association.
8
+ class HasOne < Cuprum::Collections::Association
9
+ # (see Cuprum::Collections::Association#initialize)
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])
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/collections'
4
+
5
+ module Cuprum::Collections
6
+ # Namespace for implementing specific association types.
7
+ module Associations
8
+ autoload :BelongsTo, 'cuprum/collections/associations/belongs_to'
9
+ end
10
+ end
@@ -4,71 +4,45 @@ require 'cuprum/command_factory'
4
4
 
5
5
  require 'cuprum/collections/basic'
6
6
  require 'cuprum/collections/basic/commands'
7
+ require 'cuprum/collections/collection'
7
8
 
8
9
  module Cuprum::Collections::Basic
9
10
  # Wraps an in-memory array of hashes data store as a Cuprum collection.
10
- class Collection < Cuprum::CommandFactory
11
- # @param collection_name [String, Symbol] The name of the collection.
12
- # @param data [Array<Hash>] The current data in the collection.
13
- # @param default_contract [Stannum::Constraints::Base, nil] The default
14
- # contract for validating items in the collection.
15
- # @param member_name [String] The name of a collection entity.
16
- # @param primary_key_name [Symbol] The name of the primary key attribute.
17
- # Defaults to :id.
18
- # @param primary_key_type [Class, Stannum::Constraint] The type of the
19
- # primary key attribute. Defaults to Integer.
20
- # @param qualified_name [String] The qualified name of the collection, which
21
- # should be unique. Defaults to the collection name.
22
- # @param options [Hash<Symbol>] Additional options for the command.
23
- def initialize( # rubocop:disable Metrics/ParameterLists
24
- collection_name:,
25
- data:,
26
- default_contract: nil,
27
- member_name: nil,
28
- primary_key_name: :id,
29
- primary_key_type: Integer,
30
- qualified_name: nil,
31
- **options
32
- )
33
- super()
34
-
35
- @collection_name = collection_name.to_s
36
- @data = data
37
- @default_contract = default_contract
38
- @member_name =
39
- member_name ? member_name.to_s : tools.str.singularize(@collection_name)
40
- @options = options
41
- @primary_key_name = primary_key_name
42
- @primary_key_type = primary_key_type
43
- @qualified_name = qualified_name || @collection_name
11
+ class Collection < Cuprum::Collections::Collection
12
+ # @overload initialize(data: [], entity_class: nil, name: nil, qualified_name: nil, singular_name: nil, **options)
13
+ # @param data [Array<Hash>] the current data in the collection.
14
+ # @param entity_class [Class, String] the class of entity represented by
15
+ # the relation.
16
+ # @param name [String] the name of the relation. Aliased as
17
+ # :collection_name.
18
+ # @param qualified_name [String] a scoped name for the relation.
19
+ # @param singular_name [String] the name of an entity in the relation.
20
+ # Aliased as :member_name.
21
+ # @param options [Hash] additional options for the relation.
22
+ #
23
+ # @option options primary_key_name [String] the name of the primary key
24
+ # 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
+ )
39
+
40
+ @data = data
44
41
  end
45
42
 
46
- # @return [String] the name of the collection.
47
- attr_reader :collection_name
48
-
49
43
  # @return [Array<Hash>] the current data in the collection.
50
44
  attr_reader :data
51
45
 
52
- # @return [Stannum::Constraints::Base, nil] the default contract for
53
- # validating items in the collection.
54
- attr_reader :default_contract
55
-
56
- # @return [String] the name of a collection entity.
57
- attr_reader :member_name
58
-
59
- # @return [Hash<Symbol>] additional options for the command.
60
- attr_reader :options
61
-
62
- # @return [Symbol] the name of the primary key attribute.
63
- attr_reader :primary_key_name
64
-
65
- # @return [Class, Stannum::Constraint] the type of the primary key
66
- # attribute.
67
- attr_reader :primary_key_type
68
-
69
- # @return [String] the qualified name of the collection.
70
- attr_reader :qualified_name
71
-
72
46
  command_class :assign_one do
73
47
  Cuprum::Collections::Basic::Commands::AssignOne
74
48
  .subclass(**command_options)
@@ -114,11 +88,11 @@ module Cuprum::Collections::Basic
114
88
  .subclass(**command_options)
115
89
  end
116
90
 
117
- # @return [Integer] the count of items in the collection.
118
- def count
119
- query.count
91
+ # @return [Stannum::Constraints::Base, nil] the # default contract for
92
+ # validating items in the collection.
93
+ def default_contract
94
+ @options[:default_contract]
120
95
  end
121
- alias size count
122
96
 
123
97
  # A new Query instance, used for querying against the collection data.
124
98
  #
@@ -127,22 +101,13 @@ module Cuprum::Collections::Basic
127
101
  Cuprum::Collections::Basic::Query.new(data)
128
102
  end
129
103
 
130
- private
104
+ protected
131
105
 
132
106
  def command_options
133
- @command_options ||= {
134
- collection_name: collection_name,
107
+ super().merge(
135
108
  data: data,
136
- default_contract: default_contract,
137
- member_name: member_name,
138
- primary_key_name: primary_key_name,
139
- primary_key_type: primary_key_type,
140
- **options
141
- }
142
- end
143
-
144
- def tools
145
- SleepingKingStudios::Tools::Toolbelt.instance
109
+ default_contract: default_contract
110
+ )
146
111
  end
147
112
  end
148
113
  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) # rubocop:disable Layout/LineLength
14
+ # @!method call(primary_keys:, allow_partial: false, envelope: false, scope: nil)
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
@@ -13,7 +13,7 @@ module Cuprum::Collections::Basic::Commands
13
13
  class FindMatching < Cuprum::Collections::Basic::Command
14
14
  include Cuprum::Collections::Commands::AbstractFindMatching
15
15
 
16
- # @!method call(envelope: false, limit: nil, offset: nil, order: nil, scope: nil, where: nil, &block) # rubocop:disable Layout/LineLength
16
+ # @!method call(envelope: false, limit: nil, offset: nil, order: nil, scope: nil, where: nil, &block)
17
17
  # Queries the collection for items matching the given conditions.
18
18
  #
19
19
  # @param envelope [Boolean] If true, wraps the result value in a Hash.