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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -0
- data/DEVELOPMENT.md +2 -2
- data/README.md +13 -11
- data/lib/cuprum/collections/association.rb +256 -0
- data/lib/cuprum/collections/associations/belongs_to.rb +32 -0
- data/lib/cuprum/collections/associations/has_many.rb +23 -0
- data/lib/cuprum/collections/associations/has_one.rb +23 -0
- data/lib/cuprum/collections/associations.rb +10 -0
- data/lib/cuprum/collections/basic/collection.rb +39 -74
- data/lib/cuprum/collections/basic/commands/find_many.rb +1 -1
- data/lib/cuprum/collections/basic/commands/find_matching.rb +1 -1
- data/lib/cuprum/collections/basic/repository.rb +9 -33
- data/lib/cuprum/collections/basic.rb +1 -0
- data/lib/cuprum/collections/collection.rb +154 -0
- data/lib/cuprum/collections/commands/associations/find_many.rb +161 -0
- data/lib/cuprum/collections/commands/associations/require_many.rb +48 -0
- data/lib/cuprum/collections/commands/associations.rb +13 -0
- data/lib/cuprum/collections/commands/find_one_matching.rb +1 -1
- data/lib/cuprum/collections/commands.rb +1 -0
- data/lib/cuprum/collections/errors/abstract_find_error.rb +1 -1
- data/lib/cuprum/collections/relation.rb +401 -0
- data/lib/cuprum/collections/repository.rb +71 -4
- data/lib/cuprum/collections/resource.rb +65 -0
- data/lib/cuprum/collections/rspec/contracts/association_contracts.rb +2137 -0
- data/lib/cuprum/collections/rspec/contracts/basic/command_contracts.rb +484 -0
- data/lib/cuprum/collections/rspec/contracts/basic.rb +11 -0
- data/lib/cuprum/collections/rspec/contracts/collection_contracts.rb +429 -0
- data/lib/cuprum/collections/rspec/contracts/command_contracts.rb +1462 -0
- data/lib/cuprum/collections/rspec/contracts/query_contracts.rb +1093 -0
- data/lib/cuprum/collections/rspec/contracts/relation_contracts.rb +1381 -0
- data/lib/cuprum/collections/rspec/contracts/repository_contracts.rb +605 -0
- data/lib/cuprum/collections/rspec/contracts.rb +23 -0
- data/lib/cuprum/collections/rspec/fixtures.rb +85 -82
- data/lib/cuprum/collections/rspec.rb +4 -1
- data/lib/cuprum/collections/version.rb +1 -1
- data/lib/cuprum/collections.rb +9 -4
- metadata +23 -19
- data/lib/cuprum/collections/base.rb +0 -11
- data/lib/cuprum/collections/basic/rspec/command_contract.rb +0 -392
- data/lib/cuprum/collections/rspec/assign_one_command_contract.rb +0 -168
- data/lib/cuprum/collections/rspec/build_one_command_contract.rb +0 -93
- data/lib/cuprum/collections/rspec/collection_contract.rb +0 -190
- data/lib/cuprum/collections/rspec/destroy_one_command_contract.rb +0 -108
- data/lib/cuprum/collections/rspec/find_many_command_contract.rb +0 -407
- data/lib/cuprum/collections/rspec/find_matching_command_contract.rb +0 -194
- data/lib/cuprum/collections/rspec/find_one_command_contract.rb +0 -157
- data/lib/cuprum/collections/rspec/insert_one_command_contract.rb +0 -84
- data/lib/cuprum/collections/rspec/query_builder_contract.rb +0 -92
- data/lib/cuprum/collections/rspec/query_contract.rb +0 -650
- data/lib/cuprum/collections/rspec/querying_contract.rb +0 -298
- data/lib/cuprum/collections/rspec/repository_contract.rb +0 -235
- data/lib/cuprum/collections/rspec/update_one_command_contract.rb +0 -80
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a2dd2e704041cbdb689bca94afa13c5803ada5cb0601d7c0870cea1c6740830
|
4
|
+
data.tar.gz: 0fc7380322c9dbb547354408dbe8fd513ef792c7cb8ee0000aef2b94ef68f921
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
12
|
-
- Add test cases in
|
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
|
-
|
72
|
-
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
|
-
- `#
|
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 `#
|
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.
|
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
|
-
|
436
|
-
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 `:
|
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(
|
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
|
-
|
597
|
-
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
|
@@ -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::
|
11
|
-
# @
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
super(
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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 [
|
118
|
-
|
119
|
-
|
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
|
-
|
104
|
+
protected
|
131
105
|
|
132
106
|
def command_options
|
133
|
-
|
134
|
-
collection_name: collection_name,
|
107
|
+
super().merge(
|
135
108
|
data: data,
|
136
|
-
default_contract: default_contract
|
137
|
-
|
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)
|
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)
|
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.
|