terrestrial 0.1.1 → 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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/Gemfile.lock +29 -24
  4. data/README.md +35 -17
  5. data/Rakefile +4 -9
  6. data/TODO.md +25 -18
  7. data/bin/test +31 -0
  8. data/docs/domain_object_contract.md +50 -0
  9. data/features/env.rb +4 -6
  10. data/features/example.feature +28 -28
  11. data/features/step_definitions/example_steps.rb +2 -2
  12. data/lib/terrestrial/adapters/memory_adapter.rb +241 -0
  13. data/lib/terrestrial/collection_mutability_proxy.rb +7 -2
  14. data/lib/terrestrial/dirty_map.rb +5 -0
  15. data/lib/terrestrial/error.rb +69 -0
  16. data/lib/terrestrial/graph_loader.rb +58 -35
  17. data/lib/terrestrial/graph_serializer.rb +37 -30
  18. data/lib/terrestrial/inspection_string.rb +19 -0
  19. data/lib/terrestrial/lazy_collection.rb +2 -2
  20. data/lib/terrestrial/lazy_object_proxy.rb +1 -1
  21. data/lib/terrestrial/many_to_one_association.rb +17 -11
  22. data/lib/terrestrial/public_conveniencies.rb +125 -95
  23. data/lib/terrestrial/relation_mapping.rb +30 -0
  24. data/lib/terrestrial/{mapper_facade.rb → relational_store.rb} +11 -1
  25. data/lib/terrestrial/version.rb +1 -1
  26. data/spec/config_override_spec.rb +10 -14
  27. data/spec/custom_serializers_spec.rb +4 -6
  28. data/spec/deletion_spec.rb +12 -14
  29. data/spec/error_handling/factory_error_handling_spec.rb +61 -0
  30. data/spec/error_handling/serialization_error_spec.rb +50 -0
  31. data/spec/error_handling/upsert_error_spec.rb +132 -0
  32. data/spec/graph_persistence_spec.rb +80 -24
  33. data/spec/graph_traversal_spec.rb +14 -6
  34. data/spec/new_graph_persistence_spec.rb +43 -9
  35. data/spec/object_identity_spec.rb +5 -7
  36. data/spec/ordered_association_spec.rb +4 -6
  37. data/spec/predefined_queries_spec.rb +4 -6
  38. data/spec/querying_spec.rb +4 -12
  39. data/spec/readme_examples_spec.rb +3 -6
  40. data/spec/{persistence_efficiency_spec.rb → sequel_query_efficiency_spec.rb} +101 -19
  41. data/spec/spec_helper.rb +24 -2
  42. data/spec/support/memory_adapter_test_support.rb +21 -0
  43. data/spec/support/{mapper_setup.rb → object_store_setup.rb} +5 -5
  44. data/spec/support/seed_data_setup.rb +3 -1
  45. data/spec/support/sequel_test_support.rb +58 -25
  46. data/spec/{sequel_mapper → terrestrial}/abstract_record_spec.rb +0 -0
  47. data/spec/{sequel_mapper → terrestrial}/collection_mutability_proxy_spec.rb +0 -0
  48. data/spec/{sequel_mapper → terrestrial}/deleted_record_spec.rb +0 -0
  49. data/spec/{sequel_mapper → terrestrial}/dirty_map_spec.rb +38 -6
  50. data/spec/{sequel_mapper → terrestrial}/lazy_collection_spec.rb +2 -3
  51. data/spec/{sequel_mapper → terrestrial}/lazy_object_proxy_spec.rb +0 -0
  52. data/spec/{sequel_mapper → terrestrial}/public_conveniencies_spec.rb +12 -7
  53. data/spec/{sequel_mapper → terrestrial}/upserted_record_spec.rb +0 -0
  54. data/{sequel_mapper.gemspec → terrestrial.gemspec} +3 -3
  55. metadata +47 -39
  56. data/lib/terrestrial/short_inspection_string.rb +0 -18
  57. data/spec/proxying_spec.rb +0 -88
  58. data/spec/support/mock_sequel.rb +0 -193
  59. data/spec/support/sequel_persistence_setup.rb +0 -19
@@ -11,7 +11,7 @@ RSpec.describe Terrestrial::DirtyMap do
11
11
 
12
12
  let(:storage) { {} }
13
13
 
14
- let(:loaded_record) {
14
+ let(:record) {
15
15
  create_record( namespace, identity_fields, attributes, depth)
16
16
  }
17
17
 
@@ -27,15 +27,47 @@ RSpec.describe Terrestrial::DirtyMap do
27
27
  }
28
28
  }
29
29
 
30
+ describe "#load_if_new" do
31
+ context "when a record is new" do
32
+ it "adds it to the map" do
33
+ dirty_map.load_if_new(record)
34
+
35
+ expect(storage).to include([:table_name, { id: "record/id" }])
36
+ end
37
+
38
+ it "returns the record" do
39
+ expect(dirty_map.load_if_new(record)).to eq(record)
40
+ end
41
+ end
42
+
43
+ context "when the record has already been loaded" do
44
+ let(:storage) {
45
+ {
46
+ [:table_name, { id: "record/id" }] => record
47
+ }
48
+ }
49
+
50
+ it "has no effect on the storage" do
51
+ expect {
52
+ dirty_map.load_if_new(record)
53
+ }.not_to change { storage }
54
+ end
55
+
56
+ it "returns the record" do
57
+ expect(dirty_map.load_if_new(record)).to eq(record)
58
+ end
59
+ end
60
+ end
61
+
30
62
  describe "#load" do
31
63
  it "adds the record to its storage" do
32
- dirty_map.load(loaded_record)
64
+ dirty_map.load(record)
33
65
 
34
- expect(storage.values).to include(loaded_record)
66
+ expect(storage.values).to include(record)
35
67
  end
36
68
 
37
69
  it "returns the loaded record" do
38
- expect(dirty_map.load(loaded_record)).to eq(loaded_record)
70
+ expect(dirty_map.load(record)).to eq(record)
39
71
  end
40
72
  end
41
73
 
@@ -61,7 +93,7 @@ RSpec.describe Terrestrial::DirtyMap do
61
93
 
62
94
  context "when a record with same identity has been loaded (existing record)" do
63
95
  before do
64
- dirty_map.load(loaded_record)
96
+ dirty_map.load(record)
65
97
  end
66
98
 
67
99
  context "when the record is unchanged" do
@@ -181,7 +213,7 @@ RSpec.describe Terrestrial::DirtyMap do
181
213
 
182
214
  context "when a record with same identity has been loaded (existing record)" do
183
215
  before do
184
- dirty_map.load(loaded_record)
216
+ dirty_map.load(record)
185
217
  end
186
218
 
187
219
  context "with a equivalent record" do
@@ -7,7 +7,7 @@ RSpec.describe Terrestrial::LazyCollection do
7
7
  Terrestrial::LazyCollection.new(
8
8
  database_enum,
9
9
  loader,
10
- mapper,
10
+ queries,
11
11
  )
12
12
  }
13
13
 
@@ -24,8 +24,7 @@ RSpec.describe Terrestrial::LazyCollection do
24
24
  let(:collection_size) { row_object_map.size }
25
25
 
26
26
  let(:database_enum) { [row1, row2].each.lazy }
27
-
28
- let(:mapper) { double(:mapper) }
27
+ let(:queries) { {} }
29
28
 
30
29
  let(:loader_count) { @loader_count }
31
30
  let(:loader) {
@@ -1,6 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  require "terrestrial/public_conveniencies"
4
+ require "ostruct"
4
5
 
5
6
  RSpec.describe Terrestrial::PublicConveniencies do
6
7
  subject(:conveniences) {
@@ -13,7 +14,7 @@ RSpec.describe Terrestrial::PublicConveniencies do
13
14
  end
14
15
  end
15
16
 
16
- describe "#mappers" do
17
+ describe "#object_store" do
17
18
  let(:datastore) {
18
19
  MockDatastore.new(
19
20
  {
@@ -22,7 +23,7 @@ RSpec.describe Terrestrial::PublicConveniencies do
22
23
  )
23
24
  }
24
25
 
25
- let(:mapper_config) {
26
+ let(:mappings) {
26
27
  {
27
28
  things: double(
28
29
  :thing_config,
@@ -31,7 +32,7 @@ RSpec.describe Terrestrial::PublicConveniencies do
31
32
  fields: [:id],
32
33
  associations: [],
33
34
  primary_key: [],
34
- factory: ->(x){x}
35
+ load: thing_object,
35
36
  )
36
37
  }
37
38
  }
@@ -44,14 +45,18 @@ RSpec.describe Terrestrial::PublicConveniencies do
44
45
  }
45
46
  }
46
47
 
47
- it "returns a mapper for the specified mapping" do
48
- mappers = conveniences.mappers(
49
- mappings: mapper_config,
48
+ let(:thing_object) {
49
+ OpenStruct.new(thing_record)
50
+ }
51
+
52
+ it "returns an object store for given mappings" do
53
+ object_store = conveniences.object_store(
54
+ mappings: mappings,
50
55
  datastore: datastore,
51
56
  )
52
57
 
53
58
  expect(
54
- mappers[:things].all.first.fetch(:id)
59
+ object_store[:things].all.first.id
55
60
  ).to eq("THE THING")
56
61
  end
57
62
  end
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Terrestrial::VERSION
9
9
  spec.authors = ["Stephen Best"]
10
10
  spec.email = ["bestie@gmail.com"]
11
- spec.summary = %q{A data mapping ORM to make your objects feel less alien}
12
- spec.description = %q{Terrestial persists your POROs while keeping them free of database concerns.}
11
+ spec.summary = %q{A data mapper ORM for Ruby}
12
+ spec.description = %q{A data mapper ORM for Ruby. Persists POROs, enables DDD and fast tests. Makes your objects less alien.}
13
13
  spec.homepage = "https://github.com/bestie/terrestrial"
14
14
  spec.license = "MIT"
15
15
 
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_development_dependency "pry", "~> 0.10.1"
24
24
  spec.add_development_dependency "rspec", "~> 3.1"
25
- spec.add_development_dependency "cucumber"
25
+ spec.add_development_dependency "cucumber", "~> 2.4"
26
26
  spec.add_development_dependency "pg", "~> 0.17.1"
27
27
 
28
28
  spec.add_dependency "sequel", "~> 4.16"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terrestrial
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Best
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-04 00:00:00.000000000 Z
11
+ date: 2017-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: cucumber
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '2.4'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '2.4'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: pg
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -136,10 +136,12 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '1.0'
139
- description: Terrestial persists your POROs while keeping them free of database concerns.
139
+ description: A data mapper ORM for Ruby. Persists POROs, enables DDD and fast tests.
140
+ Makes your objects less alien.
140
141
  email:
141
142
  - bestie@gmail.com
142
- executables: []
143
+ executables:
144
+ - test
143
145
  extensions: []
144
146
  extra_rdoc_files: []
145
147
  files:
@@ -154,11 +156,14 @@ files:
154
156
  - README.md
155
157
  - Rakefile
156
158
  - TODO.md
159
+ - bin/test
160
+ - docs/domain_object_contract.md
157
161
  - features/env.rb
158
162
  - features/example.feature
159
163
  - features/step_definitions/example_steps.rb
160
164
  - lib/terrestrial.rb
161
165
  - lib/terrestrial/abstract_record.rb
166
+ - lib/terrestrial/adapters/memory_adapter.rb
162
167
  - lib/terrestrial/association_loaders.rb
163
168
  - lib/terrestrial/collection_mutability_proxy.rb
164
169
  - lib/terrestrial/configurations/conventional_association_configuration.rb
@@ -166,55 +171,57 @@ files:
166
171
  - lib/terrestrial/dataset.rb
167
172
  - lib/terrestrial/deleted_record.rb
168
173
  - lib/terrestrial/dirty_map.rb
174
+ - lib/terrestrial/error.rb
169
175
  - lib/terrestrial/graph_loader.rb
170
176
  - lib/terrestrial/graph_serializer.rb
171
177
  - lib/terrestrial/identity_map.rb
178
+ - lib/terrestrial/inspection_string.rb
172
179
  - lib/terrestrial/lazy_collection.rb
173
180
  - lib/terrestrial/lazy_object_proxy.rb
174
181
  - lib/terrestrial/many_to_many_association.rb
175
182
  - lib/terrestrial/many_to_one_association.rb
176
- - lib/terrestrial/mapper_facade.rb
177
183
  - lib/terrestrial/one_to_many_association.rb
178
184
  - lib/terrestrial/public_conveniencies.rb
179
185
  - lib/terrestrial/query_order.rb
180
186
  - lib/terrestrial/relation_mapping.rb
187
+ - lib/terrestrial/relational_store.rb
181
188
  - lib/terrestrial/serializer.rb
182
- - lib/terrestrial/short_inspection_string.rb
183
189
  - lib/terrestrial/struct_factory.rb
184
190
  - lib/terrestrial/subset_queries_proxy.rb
185
191
  - lib/terrestrial/upserted_record.rb
186
192
  - lib/terrestrial/version.rb
187
- - sequel_mapper.gemspec
188
193
  - spec/config_override_spec.rb
189
194
  - spec/custom_serializers_spec.rb
190
195
  - spec/deletion_spec.rb
196
+ - spec/error_handling/factory_error_handling_spec.rb
197
+ - spec/error_handling/serialization_error_spec.rb
198
+ - spec/error_handling/upsert_error_spec.rb
191
199
  - spec/graph_persistence_spec.rb
192
200
  - spec/graph_traversal_spec.rb
193
201
  - spec/new_graph_persistence_spec.rb
194
202
  - spec/object_identity_spec.rb
195
203
  - spec/ordered_association_spec.rb
196
- - spec/persistence_efficiency_spec.rb
197
204
  - spec/predefined_queries_spec.rb
198
- - spec/proxying_spec.rb
199
205
  - spec/querying_spec.rb
200
206
  - spec/readme_examples_spec.rb
201
- - spec/sequel_mapper/abstract_record_spec.rb
202
- - spec/sequel_mapper/collection_mutability_proxy_spec.rb
203
- - spec/sequel_mapper/deleted_record_spec.rb
204
- - spec/sequel_mapper/dirty_map_spec.rb
205
- - spec/sequel_mapper/lazy_collection_spec.rb
206
- - spec/sequel_mapper/lazy_object_proxy_spec.rb
207
- - spec/sequel_mapper/public_conveniencies_spec.rb
208
- - spec/sequel_mapper/upserted_record_spec.rb
207
+ - spec/sequel_query_efficiency_spec.rb
209
208
  - spec/spec_helper.rb
210
209
  - spec/support/blog_schema.rb
211
210
  - spec/support/have_persisted_matcher.rb
212
- - spec/support/mapper_setup.rb
213
- - spec/support/mock_sequel.rb
211
+ - spec/support/memory_adapter_test_support.rb
214
212
  - spec/support/object_graph_setup.rb
213
+ - spec/support/object_store_setup.rb
215
214
  - spec/support/seed_data_setup.rb
216
- - spec/support/sequel_persistence_setup.rb
217
215
  - spec/support/sequel_test_support.rb
216
+ - spec/terrestrial/abstract_record_spec.rb
217
+ - spec/terrestrial/collection_mutability_proxy_spec.rb
218
+ - spec/terrestrial/deleted_record_spec.rb
219
+ - spec/terrestrial/dirty_map_spec.rb
220
+ - spec/terrestrial/lazy_collection_spec.rb
221
+ - spec/terrestrial/lazy_object_proxy_spec.rb
222
+ - spec/terrestrial/public_conveniencies_spec.rb
223
+ - spec/terrestrial/upserted_record_spec.rb
224
+ - terrestrial.gemspec
218
225
  homepage: https://github.com/bestie/terrestrial
219
226
  licenses:
220
227
  - MIT
@@ -235,10 +242,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
235
242
  version: '0'
236
243
  requirements: []
237
244
  rubyforge_project:
238
- rubygems_version: 2.4.5
245
+ rubygems_version: 2.5.1
239
246
  signing_key:
240
247
  specification_version: 4
241
- summary: A data mapping ORM to make your objects feel less alien
248
+ summary: A data mapper ORM for Ruby
242
249
  test_files:
243
250
  - features/env.rb
244
251
  - features/example.feature
@@ -246,30 +253,31 @@ test_files:
246
253
  - spec/config_override_spec.rb
247
254
  - spec/custom_serializers_spec.rb
248
255
  - spec/deletion_spec.rb
256
+ - spec/error_handling/factory_error_handling_spec.rb
257
+ - spec/error_handling/serialization_error_spec.rb
258
+ - spec/error_handling/upsert_error_spec.rb
249
259
  - spec/graph_persistence_spec.rb
250
260
  - spec/graph_traversal_spec.rb
251
261
  - spec/new_graph_persistence_spec.rb
252
262
  - spec/object_identity_spec.rb
253
263
  - spec/ordered_association_spec.rb
254
- - spec/persistence_efficiency_spec.rb
255
264
  - spec/predefined_queries_spec.rb
256
- - spec/proxying_spec.rb
257
265
  - spec/querying_spec.rb
258
266
  - spec/readme_examples_spec.rb
259
- - spec/sequel_mapper/abstract_record_spec.rb
260
- - spec/sequel_mapper/collection_mutability_proxy_spec.rb
261
- - spec/sequel_mapper/deleted_record_spec.rb
262
- - spec/sequel_mapper/dirty_map_spec.rb
263
- - spec/sequel_mapper/lazy_collection_spec.rb
264
- - spec/sequel_mapper/lazy_object_proxy_spec.rb
265
- - spec/sequel_mapper/public_conveniencies_spec.rb
266
- - spec/sequel_mapper/upserted_record_spec.rb
267
+ - spec/sequel_query_efficiency_spec.rb
267
268
  - spec/spec_helper.rb
268
269
  - spec/support/blog_schema.rb
269
270
  - spec/support/have_persisted_matcher.rb
270
- - spec/support/mapper_setup.rb
271
- - spec/support/mock_sequel.rb
271
+ - spec/support/memory_adapter_test_support.rb
272
272
  - spec/support/object_graph_setup.rb
273
+ - spec/support/object_store_setup.rb
273
274
  - spec/support/seed_data_setup.rb
274
- - spec/support/sequel_persistence_setup.rb
275
275
  - spec/support/sequel_test_support.rb
276
+ - spec/terrestrial/abstract_record_spec.rb
277
+ - spec/terrestrial/collection_mutability_proxy_spec.rb
278
+ - spec/terrestrial/deleted_record_spec.rb
279
+ - spec/terrestrial/dirty_map_spec.rb
280
+ - spec/terrestrial/lazy_collection_spec.rb
281
+ - spec/terrestrial/lazy_object_proxy_spec.rb
282
+ - spec/terrestrial/public_conveniencies_spec.rb
283
+ - spec/terrestrial/upserted_record_spec.rb
@@ -1,18 +0,0 @@
1
- module Terrestrial
2
- module ShortInspectionString
3
- def inspect
4
- "\#<#{self.class.name}:#{self.object_id.<<(1).to_s(16)} " +
5
- inspectable_properties.map { |property|
6
- [
7
- property,
8
- instance_variable_get("@#{property}").inspect
9
- ].join("=")
10
- }
11
- .join(" ") + ">"
12
- end
13
-
14
- def inspectable_properties
15
- []
16
- end
17
- end
18
- end
@@ -1,88 +0,0 @@
1
- require "spec_helper"
2
-
3
- require "support/mapper_setup"
4
- require "support/sequel_persistence_setup"
5
- require "support/seed_data_setup"
6
- require "terrestrial"
7
-
8
- RSpec.describe "Proxying associations" do
9
- include_context "mapper setup"
10
- include_context "sequel persistence setup"
11
- include_context "seed data setup"
12
-
13
- context "of type `has_many`" do
14
- subject(:mapper) { user_mapper }
15
-
16
- let(:user) {
17
- mapper.where(id: "users/1").first
18
- }
19
-
20
- let(:posts) { user.posts }
21
-
22
- describe "limiting datastore reads" do
23
- context "when loading the root node" do
24
- it "only performs one read" do
25
- expect {
26
- user
27
- }.to change { query_counter.read_count }.by(1)
28
- end
29
- end
30
-
31
- context "when getting a reference to an association proxy" do
32
- before { user }
33
-
34
- it "does no additional reads" do
35
- expect{
36
- user.posts
37
- }.to change { query_counter.read_count }.by(0)
38
- end
39
- end
40
-
41
- context "when iteratiing over a has many association" do
42
- before { posts }
43
-
44
- it "does a single additional read for the association collection" do
45
- expect {
46
- user.posts.each { |x| x }
47
- }.to change { query_counter.read_count }.by(1)
48
- end
49
-
50
- context "when doing this more than once" do
51
- before do
52
- posts.each { |x| x }
53
- end
54
-
55
- it "performs no additional reads" do
56
- expect {
57
- user.posts.each { |x| x }
58
- }.not_to change { query_counter.read_count }
59
- end
60
- end
61
- end
62
-
63
- context "when getting a reference to a many to many association" do
64
- before { post }
65
-
66
- let(:post) { user.posts.first }
67
-
68
- it "does no additional reads" do
69
- expect {
70
- post.categories
71
- }.to change { query_counter.read_count }.by(0)
72
- end
73
- end
74
-
75
- context "when iterating over a many to many association" do
76
- let(:category_count) { 3 }
77
-
78
- it "does 1 read" do
79
- post = user.posts.first
80
-
81
- expect {
82
- post.categories.each { |x| x }
83
- }.to change { query_counter.read_count }.by(1)
84
- end
85
- end
86
- end
87
- end
88
- end