cuprum-collections 0.3.0 → 0.4.0.rc.0

Sign up to get free protection for your applications and to get access to all the features.
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 +3 -3
  37. data/lib/cuprum/collections.rb +9 -4
  38. metadata +25 -21
  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: 41809662909130b20768087ef655e972329095ebc5dca41623fcc6c0c1503611
4
+ data.tar.gz: 340d4fdfac04c704d446bc8b61ded6ac4a4422bbadebbd46cde21e77efd387b5
5
5
  SHA512:
6
- metadata.gz: 138cf1bd095d6d03e196c90ac4779ee6d8dec8743f8cb321c4114117c707ef0124f378642653beef0e3db1c0d127cebd05967a4356ce5361cd3294bd298642e7
7
- data.tar.gz: 968b185b8e1b0447b55acc093387ad527e0ba5154b0e4a24d2ace52cf258ca29939eefa0cc772451703d1b56286dce907c84402a735a360152d3573ea8cb5db7
6
+ metadata.gz: 6717290b09b85b7295a08c47adb3d145f35ffc09825ecf4a2fef239a596c88d1d9c5875214848e161ea76c9cf9802b5a4741a840103bac46217f10856236d425
7
+ data.tar.gz: 3f422dc13bf6845ee0b199550f79e6787bca096687c358e61c12b74fd54d7a4d73d20f94ecb053162670a364e4ca3ae04233c9b29ed9c9ac8e18a939b323022b
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.