cuprum-collections 0.2.0 → 0.3.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/README.md +255 -8
  4. data/lib/cuprum/collections/basic/collection.rb +13 -0
  5. data/lib/cuprum/collections/basic/commands/destroy_one.rb +4 -3
  6. data/lib/cuprum/collections/basic/commands/find_many.rb +1 -1
  7. data/lib/cuprum/collections/basic/commands/insert_one.rb +4 -3
  8. data/lib/cuprum/collections/basic/commands/update_one.rb +4 -3
  9. data/lib/cuprum/collections/basic/query.rb +3 -3
  10. data/lib/cuprum/collections/commands/abstract_find_many.rb +33 -32
  11. data/lib/cuprum/collections/commands/abstract_find_one.rb +4 -3
  12. data/lib/cuprum/collections/commands/create.rb +60 -0
  13. data/lib/cuprum/collections/commands/find_one_matching.rb +134 -0
  14. data/lib/cuprum/collections/commands/update.rb +74 -0
  15. data/lib/cuprum/collections/commands/upsert.rb +162 -0
  16. data/lib/cuprum/collections/commands.rb +7 -2
  17. data/lib/cuprum/collections/errors/abstract_find_error.rb +210 -0
  18. data/lib/cuprum/collections/errors/already_exists.rb +4 -72
  19. data/lib/cuprum/collections/errors/extra_attributes.rb +8 -18
  20. data/lib/cuprum/collections/errors/failed_validation.rb +5 -18
  21. data/lib/cuprum/collections/errors/invalid_parameters.rb +7 -15
  22. data/lib/cuprum/collections/errors/invalid_query.rb +5 -15
  23. data/lib/cuprum/collections/errors/missing_default_contract.rb +5 -17
  24. data/lib/cuprum/collections/errors/not_found.rb +4 -67
  25. data/lib/cuprum/collections/errors/not_unique.rb +18 -0
  26. data/lib/cuprum/collections/errors/unknown_operator.rb +7 -17
  27. data/lib/cuprum/collections/errors.rb +13 -1
  28. data/lib/cuprum/collections/queries/ordering.rb +2 -2
  29. data/lib/cuprum/collections/repository.rb +23 -10
  30. data/lib/cuprum/collections/rspec/collection_contract.rb +140 -103
  31. data/lib/cuprum/collections/rspec/destroy_one_command_contract.rb +8 -6
  32. data/lib/cuprum/collections/rspec/find_many_command_contract.rb +114 -34
  33. data/lib/cuprum/collections/rspec/find_one_command_contract.rb +12 -9
  34. data/lib/cuprum/collections/rspec/insert_one_command_contract.rb +4 -3
  35. data/lib/cuprum/collections/rspec/query_contract.rb +3 -3
  36. data/lib/cuprum/collections/rspec/querying_contract.rb +2 -2
  37. data/lib/cuprum/collections/rspec/repository_contract.rb +167 -93
  38. data/lib/cuprum/collections/rspec/update_one_command_contract.rb +4 -3
  39. data/lib/cuprum/collections/version.rb +1 -1
  40. data/lib/cuprum/collections.rb +1 -0
  41. metadata +20 -89
@@ -1,57 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rspec/sleeping_king_studios/contract'
4
+
3
5
  require 'cuprum/collections/rspec'
4
6
 
5
7
  module Cuprum::Collections::RSpec
6
8
  # Contract validating the behavior of a Repository.
7
- REPOSITORY_CONTRACT = lambda do
8
- describe '#[]' do
9
- let(:error_class) do
10
- described_class::UndefinedCollectionError
11
- end
12
- let(:error_message) do
13
- "repository does not define collection #{collection_name.inspect}"
14
- end
15
-
16
- it { expect(repository).to respond_to(:[]).with(1).argument }
17
-
18
- describe 'with nil' do
19
- let(:collection_name) { nil }
20
-
21
- it 'should raise an exception' do
22
- expect { repository[collection_name] }
23
- .to raise_error(error_class, error_message)
9
+ module RepositoryContract
10
+ extend RSpec::SleepingKingStudios::Contract
11
+
12
+ # @!method apply(example_group)
13
+ # Adds the contract to the example group.
14
+ #
15
+ # @param example_group [RSpec::Core::ExampleGroup] The example group to
16
+ # which the contract is applied.
17
+ contract do
18
+ describe '#[]' do
19
+ let(:error_class) do
20
+ described_class::UndefinedCollectionError
24
21
  end
25
- end
26
-
27
- describe 'with an object' do
28
- let(:collection_name) { Object.new.freeze }
29
-
30
- it 'should raise an exception' do
31
- expect { repository[collection_name] }
32
- .to raise_error(error_class, error_message)
22
+ let(:error_message) do
23
+ "repository does not define collection #{collection_name.inspect}"
33
24
  end
34
- end
35
25
 
36
- describe 'with an invalid string' do
37
- let(:collection_name) { 'invalid_name' }
26
+ it { expect(repository).to respond_to(:[]).with(1).argument }
38
27
 
39
- it 'should raise an exception' do
40
- expect { repository[collection_name] }
41
- .to raise_error(error_class, error_message)
28
+ describe 'with nil' do
29
+ let(:collection_name) { nil }
30
+
31
+ it 'should raise an exception' do
32
+ expect { repository[collection_name] }
33
+ .to raise_error(error_class, error_message)
34
+ end
42
35
  end
43
- end
44
36
 
45
- describe 'with an invalid symbol' do
46
- let(:collection_name) { :invalid_name }
37
+ describe 'with an object' do
38
+ let(:collection_name) { Object.new.freeze }
47
39
 
48
- it 'should raise an exception' do
49
- expect { repository[collection_name] }
50
- .to raise_error(error_class, error_message)
40
+ it 'should raise an exception' do
41
+ expect { repository[collection_name] }
42
+ .to raise_error(error_class, error_message)
43
+ end
51
44
  end
52
- end
53
45
 
54
- wrap_context 'when the repository has many collections' do
55
46
  describe 'with an invalid string' do
56
47
  let(:collection_name) { 'invalid_name' }
57
48
 
@@ -70,91 +61,174 @@ module Cuprum::Collections::RSpec
70
61
  end
71
62
  end
72
63
 
73
- describe 'with a valid string' do
74
- let(:collection_name) { collection_names.first }
64
+ wrap_context 'when the repository has many collections' do
65
+ describe 'with an invalid string' do
66
+ let(:collection_name) { 'invalid_name' }
75
67
 
76
- it { expect(repository[collection_name]).to be books_collection }
77
- end
68
+ it 'should raise an exception' do
69
+ expect { repository[collection_name] }
70
+ .to raise_error(error_class, error_message)
71
+ end
72
+ end
78
73
 
79
- describe 'with a valid symbol' do
80
- let(:collection_name) { collection_names.first.intern }
74
+ describe 'with an invalid symbol' do
75
+ let(:collection_name) { :invalid_name }
81
76
 
82
- it { expect(repository[collection_name]).to be books_collection }
77
+ it 'should raise an exception' do
78
+ expect { repository[collection_name] }
79
+ .to raise_error(error_class, error_message)
80
+ end
81
+ end
82
+
83
+ describe 'with a valid string' do
84
+ let(:collection) { collections.values.first }
85
+ let(:collection_name) { collections.keys.first }
86
+
87
+ it { expect(repository[collection_name]).to be collection }
88
+ end
89
+
90
+ describe 'with a valid symbol' do
91
+ let(:collection) { collections.values.first }
92
+ let(:collection_name) { collections.keys.first.intern }
93
+
94
+ it { expect(repository[collection_name]).to be collection }
95
+ end
83
96
  end
84
97
  end
85
- end
86
98
 
87
- describe '#add' do
88
- let(:error_class) do
89
- described_class::InvalidCollectionError
90
- end
91
- let(:error_message) do
92
- "#{collection.inspect} is not a valid collection"
93
- end
99
+ describe '#add' do
100
+ let(:error_class) do
101
+ described_class::InvalidCollectionError
102
+ end
103
+ let(:error_message) do
104
+ "#{collection.inspect} is not a valid collection"
105
+ end
94
106
 
95
- it { expect(repository).to respond_to(:add).with(1).argument }
107
+ it 'should define the method' do
108
+ expect(repository)
109
+ .to respond_to(:add)
110
+ .with(1).argument
111
+ .and_keywords(:force)
112
+ end
96
113
 
97
- it 'should alias #add as #<<' do
98
- expect(repository.method(:<<)).to be == repository.method(:add)
99
- end
114
+ it 'should alias #add as #<<' do
115
+ expect(repository.method(:<<)).to be == repository.method(:add)
116
+ end
100
117
 
101
- describe 'with nil' do
102
- let(:collection) { nil }
118
+ describe 'with nil' do
119
+ let(:collection) { nil }
103
120
 
104
- it 'should raise an exception' do
105
- expect { repository.add(collection) }
106
- .to raise_error(error_class, error_message)
121
+ it 'should raise an exception' do
122
+ expect { repository.add(collection) }
123
+ .to raise_error(error_class, error_message)
124
+ end
107
125
  end
108
- end
109
126
 
110
- describe 'with an object' do
111
- let(:collection) { Object.new.freeze }
127
+ describe 'with an object' do
128
+ let(:collection) { Object.new.freeze }
112
129
 
113
- it 'should raise an exception' do
114
- expect { repository.add(collection) }
115
- .to raise_error(error_class, error_message)
130
+ it 'should raise an exception' do
131
+ expect { repository.add(collection) }
132
+ .to raise_error(error_class, error_message)
133
+ end
116
134
  end
117
- end
118
135
 
119
- describe 'with a collection' do
120
- it { expect(repository.add(example_collection)).to be repository }
136
+ describe 'with a collection' do
137
+ it { expect(repository.add(example_collection)).to be repository }
121
138
 
122
- it 'should add the collection to the repository' do
123
- repository.add(example_collection)
139
+ it 'should add the collection to the repository' do
140
+ repository.add(example_collection)
124
141
 
125
- expect(repository[example_collection.collection_name])
126
- .to be example_collection
127
- end
128
- end
129
- end
142
+ expect(repository[example_collection.qualified_name])
143
+ .to be example_collection
144
+ end
130
145
 
131
- describe '#key?' do
132
- it { expect(repository).to respond_to(:key?).with(1).argument }
146
+ describe 'with force: true' do
147
+ it 'should add the collection to the repository' do
148
+ repository.add(example_collection, force: true)
133
149
 
134
- it { expect(repository.key? nil).to be false }
150
+ expect(repository[example_collection.qualified_name])
151
+ .to be example_collection
152
+ end
153
+ end
135
154
 
136
- it { expect(repository.key? Object.new.freeze).to be false }
155
+ context 'when the collection already exists' do
156
+ let(:error_message) do
157
+ "collection #{example_collection.qualified_name} already exists"
158
+ end
159
+
160
+ before(:example) do
161
+ allow(repository)
162
+ .to receive(:key?)
163
+ .with(example_collection.qualified_name)
164
+ .and_return(true)
165
+ end
166
+
167
+ it 'should raise an exception' do
168
+ expect { repository.add(example_collection) }
169
+ .to raise_error(
170
+ described_class::DuplicateCollectionError,
171
+ error_message
172
+ )
173
+ end
174
+
175
+ it 'should not update the repository' do
176
+ begin
177
+ repository.add(example_collection)
178
+ rescue described_class::DuplicateCollectionError
179
+ # Do nothing.
180
+ end
181
+
182
+ expect { repository[example_collection.qualified_name] }
183
+ .to raise_error(
184
+ described_class::UndefinedCollectionError,
185
+ 'repository does not define collection ' \
186
+ "#{example_collection.qualified_name.inspect}"
187
+ )
188
+ end
189
+
190
+ describe 'with force: true' do
191
+ it 'should add the collection to the repository' do
192
+ repository.add(example_collection, force: true)
193
+
194
+ expect(repository[example_collection.qualified_name])
195
+ .to be example_collection
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
137
201
 
138
- it { expect(repository.key? 'invalid_name').to be false }
202
+ describe '#key?' do
203
+ it { expect(repository).to respond_to(:key?).with(1).argument }
139
204
 
140
- it { expect(repository.key? :invalid_name).to be false }
205
+ it { expect(repository.key? nil).to be false }
206
+
207
+ it { expect(repository.key? Object.new.freeze).to be false }
141
208
 
142
- wrap_context 'when the repository has many collections' do
143
209
  it { expect(repository.key? 'invalid_name').to be false }
144
210
 
145
211
  it { expect(repository.key? :invalid_name).to be false }
146
212
 
147
- it { expect(repository.key? collection_names.first).to be true }
213
+ wrap_context 'when the repository has many collections' do
214
+ it { expect(repository.key? 'invalid_name').to be false }
215
+
216
+ it { expect(repository.key? :invalid_name).to be false }
148
217
 
149
- it { expect(repository.key? collection_names.first.intern).to be true }
218
+ it { expect(repository.key? collections.keys.first).to be true }
219
+
220
+ it 'should include the key' do
221
+ expect(repository.key? collections.keys.first.intern).to be true
222
+ end
223
+ end
150
224
  end
151
- end
152
225
 
153
- describe '#keys' do
154
- include_examples 'should define reader', :keys, []
226
+ describe '#keys' do
227
+ include_examples 'should define reader', :keys, []
155
228
 
156
- wrap_context 'when the repository has many collections' do
157
- it { expect(repository.keys).to be == collection_names }
229
+ wrap_context 'when the repository has many collections' do
230
+ it { expect(repository.keys).to be == collections.keys }
231
+ end
158
232
  end
159
233
  end
160
234
  end
@@ -32,9 +32,10 @@ module Cuprum::Collections::RSpec
32
32
  context 'when the item does not exist in the collection' do
33
33
  let(:expected_error) do
34
34
  Cuprum::Collections::Errors::NotFound.new(
35
- collection_name: collection_name,
36
- primary_key_name: primary_key_name,
37
- primary_key_values: attributes[primary_key_name]
35
+ attribute_name: primary_key_name,
36
+ attribute_value: attributes[primary_key_name],
37
+ collection_name: collection_name,
38
+ primary_key: true
38
39
  )
39
40
  end
40
41
  let(:matching_data) { mapped_data.first }
@@ -11,7 +11,7 @@ module Cuprum
11
11
  # Major version.
12
12
  MAJOR = 0
13
13
  # Minor version.
14
- MINOR = 2
14
+ MINOR = 3
15
15
  # Patch version.
16
16
  PATCH = 0
17
17
  # Prerelease version.
@@ -9,6 +9,7 @@ module Cuprum
9
9
  autoload :Base, 'cuprum/collections/base'
10
10
  autoload :Basic, 'cuprum/collections/basic'
11
11
  autoload :Command, 'cuprum/collections/command'
12
+ autoload :Errors, 'cuprum/collections/errors'
12
13
 
13
14
  # @return [String] the absolute path to the gem directory.
14
15
  def self.gem_path
metadata CHANGED
@@ -1,119 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuprum-collections
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob "Merlin" Smith
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-31 00:00:00.000000000 Z
11
+ date: 2023-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cuprum
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0.11'
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '2.0'
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- version: '0.11'
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '2.0'
33
- - !ruby/object:Gem::Dependency
34
- name: stannum
35
15
  requirement: !ruby/object:Gem::Requirement
36
16
  requirements:
37
17
  - - "~>"
38
18
  - !ruby/object:Gem::Version
39
- version: '0.2'
19
+ version: '1.1'
40
20
  type: :runtime
41
21
  prerelease: false
42
22
  version_requirements: !ruby/object:Gem::Requirement
43
23
  requirements:
44
24
  - - "~>"
45
25
  - !ruby/object:Gem::Version
46
- version: '0.2'
47
- - !ruby/object:Gem::Dependency
48
- name: rspec
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '3.9'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '3.9'
61
- - !ruby/object:Gem::Dependency
62
- name: rspec-sleeping_king_studios
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '2.5'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '2.5'
26
+ version: '1.1'
75
27
  - !ruby/object:Gem::Dependency
76
- name: rubocop
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '1.22'
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '1.22'
89
- - !ruby/object:Gem::Dependency
90
- name: rubocop-rspec
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '2.5'
96
- type: :development
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: '2.5'
103
- - !ruby/object:Gem::Dependency
104
- name: simplecov
28
+ name: stannum
105
29
  requirement: !ruby/object:Gem::Requirement
106
30
  requirements:
107
31
  - - "~>"
108
32
  - !ruby/object:Gem::Version
109
- version: '0.18'
110
- type: :development
33
+ version: '0.3'
34
+ type: :runtime
111
35
  prerelease: false
112
36
  version_requirements: !ruby/object:Gem::Requirement
113
37
  requirements:
114
38
  - - "~>"
115
39
  - !ruby/object:Gem::Version
116
- version: '0.18'
40
+ version: '0.3'
117
41
  description: An adapter library to provide a consistent interface between data stores.
118
42
  email:
119
43
  - merlin@sleepingkingstudios.com
@@ -151,6 +75,10 @@ files:
151
75
  - lib/cuprum/collections/commands/abstract_find_many.rb
152
76
  - lib/cuprum/collections/commands/abstract_find_matching.rb
153
77
  - lib/cuprum/collections/commands/abstract_find_one.rb
78
+ - lib/cuprum/collections/commands/create.rb
79
+ - lib/cuprum/collections/commands/find_one_matching.rb
80
+ - lib/cuprum/collections/commands/update.rb
81
+ - lib/cuprum/collections/commands/upsert.rb
154
82
  - lib/cuprum/collections/constraints.rb
155
83
  - lib/cuprum/collections/constraints/attribute_name.rb
156
84
  - lib/cuprum/collections/constraints/order.rb
@@ -161,6 +89,7 @@ files:
161
89
  - lib/cuprum/collections/constraints/ordering.rb
162
90
  - lib/cuprum/collections/constraints/query_hash.rb
163
91
  - lib/cuprum/collections/errors.rb
92
+ - lib/cuprum/collections/errors/abstract_find_error.rb
164
93
  - lib/cuprum/collections/errors/already_exists.rb
165
94
  - lib/cuprum/collections/errors/extra_attributes.rb
166
95
  - lib/cuprum/collections/errors/failed_validation.rb
@@ -168,6 +97,7 @@ files:
168
97
  - lib/cuprum/collections/errors/invalid_query.rb
169
98
  - lib/cuprum/collections/errors/missing_default_contract.rb
170
99
  - lib/cuprum/collections/errors/not_found.rb
100
+ - lib/cuprum/collections/errors/not_unique.rb
171
101
  - lib/cuprum/collections/errors/unknown_operator.rb
172
102
  - lib/cuprum/collections/queries.rb
173
103
  - lib/cuprum/collections/queries/ordering.rb
@@ -200,7 +130,8 @@ licenses:
200
130
  metadata:
201
131
  bug_tracker_uri: https://github.com/sleepingkingstudios/cuprum-collections/issues
202
132
  source_code_uri: https://github.com/sleepingkingstudios/cuprum-collections
203
- post_install_message:
133
+ rubygems_mfa_required: 'true'
134
+ post_install_message:
204
135
  rdoc_options: []
205
136
  require_paths:
206
137
  - lib
@@ -208,15 +139,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
208
139
  requirements:
209
140
  - - ">="
210
141
  - !ruby/object:Gem::Version
211
- version: 2.6.0
142
+ version: 2.7.0
212
143
  required_rubygems_version: !ruby/object:Gem::Requirement
213
144
  requirements:
214
145
  - - ">="
215
146
  - !ruby/object:Gem::Version
216
147
  version: '0'
217
148
  requirements: []
218
- rubygems_version: 3.1.2
219
- signing_key:
149
+ rubygems_version: 3.4.13
150
+ signing_key:
220
151
  specification_version: 4
221
152
  summary: A data abstraction layer based on the Cuprum library.
222
153
  test_files: []