terrestrial 0.1.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile.lock +29 -24
- data/README.md +35 -17
- data/Rakefile +4 -9
- data/TODO.md +25 -18
- data/bin/test +31 -0
- data/docs/domain_object_contract.md +50 -0
- data/features/env.rb +4 -6
- data/features/example.feature +28 -28
- data/features/step_definitions/example_steps.rb +2 -2
- data/lib/terrestrial/adapters/memory_adapter.rb +241 -0
- data/lib/terrestrial/collection_mutability_proxy.rb +7 -2
- data/lib/terrestrial/dirty_map.rb +5 -0
- data/lib/terrestrial/error.rb +69 -0
- data/lib/terrestrial/graph_loader.rb +58 -35
- data/lib/terrestrial/graph_serializer.rb +37 -30
- data/lib/terrestrial/inspection_string.rb +19 -0
- data/lib/terrestrial/lazy_collection.rb +2 -2
- data/lib/terrestrial/lazy_object_proxy.rb +1 -1
- data/lib/terrestrial/many_to_one_association.rb +17 -11
- data/lib/terrestrial/public_conveniencies.rb +125 -95
- data/lib/terrestrial/relation_mapping.rb +30 -0
- data/lib/terrestrial/{mapper_facade.rb → relational_store.rb} +11 -1
- data/lib/terrestrial/version.rb +1 -1
- data/spec/config_override_spec.rb +10 -14
- data/spec/custom_serializers_spec.rb +4 -6
- data/spec/deletion_spec.rb +12 -14
- data/spec/error_handling/factory_error_handling_spec.rb +61 -0
- data/spec/error_handling/serialization_error_spec.rb +50 -0
- data/spec/error_handling/upsert_error_spec.rb +132 -0
- data/spec/graph_persistence_spec.rb +80 -24
- data/spec/graph_traversal_spec.rb +14 -6
- data/spec/new_graph_persistence_spec.rb +43 -9
- data/spec/object_identity_spec.rb +5 -7
- data/spec/ordered_association_spec.rb +4 -6
- data/spec/predefined_queries_spec.rb +4 -6
- data/spec/querying_spec.rb +4 -12
- data/spec/readme_examples_spec.rb +3 -6
- data/spec/{persistence_efficiency_spec.rb → sequel_query_efficiency_spec.rb} +101 -19
- data/spec/spec_helper.rb +24 -2
- data/spec/support/memory_adapter_test_support.rb +21 -0
- data/spec/support/{mapper_setup.rb → object_store_setup.rb} +5 -5
- data/spec/support/seed_data_setup.rb +3 -1
- data/spec/support/sequel_test_support.rb +58 -25
- data/spec/{sequel_mapper → terrestrial}/abstract_record_spec.rb +0 -0
- data/spec/{sequel_mapper → terrestrial}/collection_mutability_proxy_spec.rb +0 -0
- data/spec/{sequel_mapper → terrestrial}/deleted_record_spec.rb +0 -0
- data/spec/{sequel_mapper → terrestrial}/dirty_map_spec.rb +38 -6
- data/spec/{sequel_mapper → terrestrial}/lazy_collection_spec.rb +2 -3
- data/spec/{sequel_mapper → terrestrial}/lazy_object_proxy_spec.rb +0 -0
- data/spec/{sequel_mapper → terrestrial}/public_conveniencies_spec.rb +12 -7
- data/spec/{sequel_mapper → terrestrial}/upserted_record_spec.rb +0 -0
- data/{sequel_mapper.gemspec → terrestrial.gemspec} +3 -3
- metadata +47 -39
- data/lib/terrestrial/short_inspection_string.rb +0 -18
- data/spec/proxying_spec.rb +0 -88
- data/spec/support/mock_sequel.rb +0 -193
- data/spec/support/sequel_persistence_setup.rb +0 -19
@@ -1,3 +1,7 @@
|
|
1
|
+
require "terrestrial/error"
|
2
|
+
require "terrestrial/upserted_record"
|
3
|
+
require "terrestrial/deleted_record"
|
4
|
+
|
1
5
|
module Terrestrial
|
2
6
|
class RelationMapping
|
3
7
|
def initialize(name:, namespace:, fields:, primary_key:, factory:, serializer:, associations:, subsets:)
|
@@ -12,11 +16,18 @@ module Terrestrial
|
|
12
16
|
end
|
13
17
|
|
14
18
|
attr_reader :name, :namespace, :fields, :primary_key, :factory, :serializer, :associations, :subsets
|
19
|
+
private :factory, :serializer
|
15
20
|
|
16
21
|
def add_association(name, new_association)
|
17
22
|
@associations = associations.merge(name => new_association)
|
18
23
|
end
|
19
24
|
|
25
|
+
def load(record)
|
26
|
+
factory.call(record)
|
27
|
+
rescue => e
|
28
|
+
raise LoadError.new(namespace, factory, record, e)
|
29
|
+
end
|
30
|
+
|
20
31
|
def serialize(object, depth, foreign_keys = {})
|
21
32
|
object_attributes = serializer.call(object)
|
22
33
|
|
@@ -24,8 +35,18 @@ module Terrestrial
|
|
24
35
|
record(object_attributes, depth, foreign_keys),
|
25
36
|
extract_associations(object_attributes)
|
26
37
|
]
|
38
|
+
rescue => e
|
39
|
+
raise SerializationError.new(name, serializer, object, e)
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete(object, depth)
|
43
|
+
object_attributes = serializer.call(object)
|
44
|
+
|
45
|
+
[deleted_record(object_attributes, depth)]
|
27
46
|
end
|
28
47
|
|
48
|
+
private
|
49
|
+
|
29
50
|
def record(attributes, depth, foreign_keys)
|
30
51
|
UpsertedRecord.new(
|
31
52
|
namespace,
|
@@ -35,6 +56,15 @@ module Terrestrial
|
|
35
56
|
)
|
36
57
|
end
|
37
58
|
|
59
|
+
def deleted_record(attributes, depth)
|
60
|
+
DeletedRecord.new(
|
61
|
+
namespace,
|
62
|
+
primary_key,
|
63
|
+
attributes,
|
64
|
+
depth,
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
38
68
|
def extract_associations(attributes)
|
39
69
|
Hash[
|
40
70
|
associations.map { |name, _association|
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require "terrestrial/graph_serializer"
|
2
2
|
require "terrestrial/graph_loader"
|
3
|
+
require "terrestrial/inspection_string"
|
3
4
|
|
4
5
|
module Terrestrial
|
5
|
-
class
|
6
|
+
class RelationalStore
|
6
7
|
include Enumerable
|
8
|
+
include InspectionString
|
7
9
|
|
8
10
|
def initialize(mappings:, mapping_name:, datastore:, dataset:, load_pipeline:, dump_pipeline:)
|
9
11
|
@mappings = mappings
|
@@ -133,5 +135,13 @@ module Terrestrial
|
|
133
135
|
object_load_pipeline: load_pipeline,
|
134
136
|
)
|
135
137
|
end
|
138
|
+
|
139
|
+
def inspectable_properties
|
140
|
+
[
|
141
|
+
:mapping_name,
|
142
|
+
:dataset,
|
143
|
+
:eager_load,
|
144
|
+
]
|
145
|
+
end
|
136
146
|
end
|
137
147
|
end
|
data/lib/terrestrial/version.rb
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
require "ostruct"
|
3
3
|
|
4
|
-
require "support/
|
5
|
-
require "support/sequel_persistence_setup"
|
4
|
+
require "support/object_store_setup"
|
6
5
|
require "support/seed_data_setup"
|
7
6
|
require "terrestrial"
|
8
7
|
|
9
8
|
require "terrestrial/configurations/conventional_configuration"
|
10
9
|
|
11
10
|
RSpec.describe "Configuration override" do
|
12
|
-
include_context "
|
13
|
-
include_context "sequel persistence setup"
|
11
|
+
include_context "object store setup"
|
14
12
|
include_context "seed data setup"
|
15
13
|
|
16
|
-
let(:
|
17
|
-
Terrestrial.
|
14
|
+
let(:object_store) {
|
15
|
+
Terrestrial.object_store(mappings: override_config, datastore: datastore)
|
18
16
|
}
|
19
17
|
|
20
18
|
let(:override_config) {
|
@@ -26,7 +24,7 @@ RSpec.describe "Configuration override" do
|
|
26
24
|
}
|
27
25
|
|
28
26
|
let(:user) {
|
29
|
-
|
27
|
+
object_store[:users].where(id: "users/1").first
|
30
28
|
}
|
31
29
|
|
32
30
|
context "override the root mapper factory" do
|
@@ -89,15 +87,13 @@ RSpec.describe "Configuration override" do
|
|
89
87
|
end
|
90
88
|
}
|
91
89
|
|
92
|
-
let(:datastore) { db_connection }
|
93
|
-
|
94
90
|
let(:unconventional_table_name) {
|
95
91
|
:users_is_called_this_weird_thing_perhaps_for_legacy_reasons
|
96
92
|
}
|
97
93
|
|
98
94
|
it "maps data from the specified relation" do
|
99
95
|
expect(
|
100
|
-
|
96
|
+
object_store[:users].map(&:id)
|
101
97
|
).to eq(["users/1", "users/2", "users/3"])
|
102
98
|
end
|
103
99
|
end
|
@@ -184,10 +180,10 @@ RSpec.describe "Configuration override" do
|
|
184
180
|
}
|
185
181
|
|
186
182
|
it "provides access to the same data via the different configs" do
|
187
|
-
expect(
|
188
|
-
expect(
|
189
|
-
expect(
|
190
|
-
expect(
|
183
|
+
expect(object_store[:t1_users].first.id).to eq("users/1")
|
184
|
+
expect(object_store[:t1_users].first).to be_a(TypeOneUser)
|
185
|
+
expect(object_store[:t2_users].first.id).to eq("users/1")
|
186
|
+
expect(object_store[:t2_users].first).to be_a(TypeTwoUser)
|
191
187
|
end
|
192
188
|
end
|
193
189
|
end
|
@@ -1,19 +1,17 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
require "support/have_persisted_matcher"
|
4
|
-
require "support/
|
5
|
-
require "support/sequel_persistence_setup"
|
4
|
+
require "support/object_store_setup"
|
6
5
|
require "support/seed_data_setup"
|
7
6
|
require "terrestrial"
|
8
7
|
|
9
8
|
require "terrestrial/configurations/conventional_configuration"
|
10
9
|
|
11
10
|
RSpec.describe "Config override" do
|
12
|
-
include_context "
|
13
|
-
include_context "sequel persistence setup"
|
11
|
+
include_context "object store setup"
|
14
12
|
include_context "seed data setup"
|
15
13
|
|
16
|
-
let(:user) {
|
14
|
+
let(:user) { object_store[:users].where(id: "users/1").first }
|
17
15
|
|
18
16
|
context "with an object that has private fields" do
|
19
17
|
let(:user_serializer) {
|
@@ -36,7 +34,7 @@ RSpec.describe "Config override" do
|
|
36
34
|
user.first_name = "This won't work"
|
37
35
|
user.last_name = "because the serialzer is weird"
|
38
36
|
|
39
|
-
|
37
|
+
object_store[:users].save(user)
|
40
38
|
|
41
39
|
expect(datastore).to have_persisted(:users, hash_including(
|
42
40
|
id: user.id,
|
data/spec/deletion_spec.rb
CHANGED
@@ -1,29 +1,27 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
require "support/
|
4
|
-
require "support/sequel_persistence_setup"
|
3
|
+
require "support/object_store_setup"
|
5
4
|
require "support/seed_data_setup"
|
6
5
|
require "support/have_persisted_matcher"
|
7
6
|
require "terrestrial"
|
8
7
|
|
9
8
|
RSpec.describe "Deletion" do
|
10
|
-
include_context "
|
11
|
-
include_context "sequel persistence setup"
|
9
|
+
include_context "object store setup"
|
12
10
|
include_context "seed data setup"
|
13
11
|
|
14
|
-
subject(:
|
12
|
+
subject(:user_store) { object_store[:users] }
|
15
13
|
|
16
14
|
let(:user) {
|
17
|
-
|
15
|
+
user_store.where(id: "users/1").first
|
18
16
|
}
|
19
17
|
|
20
18
|
let(:reloaded_user) {
|
21
|
-
|
19
|
+
user_store.where(id: "users/1").first
|
22
20
|
}
|
23
21
|
|
24
22
|
describe "Deleting the root" do
|
25
23
|
it "deletes the root object" do
|
26
|
-
|
24
|
+
user_store.delete(user, cascade: true)
|
27
25
|
|
28
26
|
expect(datastore).not_to have_persisted(
|
29
27
|
:users,
|
@@ -37,7 +35,7 @@ RSpec.describe "Deletion" do
|
|
37
35
|
end
|
38
36
|
|
39
37
|
it "deletes the root object" do
|
40
|
-
|
38
|
+
user_store.delete(user)
|
41
39
|
|
42
40
|
expect(datastore).not_to have_persisted(
|
43
41
|
:users,
|
@@ -47,7 +45,7 @@ RSpec.describe "Deletion" do
|
|
47
45
|
|
48
46
|
it "does not delete the child objects" do
|
49
47
|
expect {
|
50
|
-
|
48
|
+
user_store.delete(user)
|
51
49
|
}.not_to change { [datastore[:posts], datastore[:comments]].map(&:count) }
|
52
50
|
end
|
53
51
|
end
|
@@ -64,7 +62,7 @@ RSpec.describe "Deletion" do
|
|
64
62
|
|
65
63
|
it "deletes the specified node" do
|
66
64
|
user.posts.delete(post)
|
67
|
-
|
65
|
+
user_store.save(user)
|
68
66
|
|
69
67
|
expect(datastore).not_to have_persisted(
|
70
68
|
:posts,
|
@@ -74,7 +72,7 @@ RSpec.describe "Deletion" do
|
|
74
72
|
|
75
73
|
it "does not delete the parent object" do
|
76
74
|
user.posts.delete(post)
|
77
|
-
|
75
|
+
user_store.save(user)
|
78
76
|
|
79
77
|
expect(datastore).to have_persisted(
|
80
78
|
:users,
|
@@ -84,7 +82,7 @@ RSpec.describe "Deletion" do
|
|
84
82
|
|
85
83
|
it "does not delete the sibling objects" do
|
86
84
|
user.posts.delete(post)
|
87
|
-
|
85
|
+
user_store.save(user)
|
88
86
|
|
89
87
|
expect(reloaded_user.posts.count).to be > 0
|
90
88
|
end
|
@@ -92,7 +90,7 @@ RSpec.describe "Deletion" do
|
|
92
90
|
it "does not cascade delete" do
|
93
91
|
expect {
|
94
92
|
user.posts.delete(post)
|
95
|
-
|
93
|
+
user_store.save(user)
|
96
94
|
}.not_to change {
|
97
95
|
datastore[:comments].map { |r| r.fetch(:id) }
|
98
96
|
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "terrestrial"
|
2
|
+
require "terrestrial/configurations/conventional_configuration"
|
3
|
+
|
4
|
+
RSpec.describe "factory error handling" do
|
5
|
+
context "factory with too few parameters" do
|
6
|
+
before do
|
7
|
+
seed_user(record)
|
8
|
+
override_user_factory_with(no_parameters_factory)
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:record) {
|
12
|
+
{
|
13
|
+
id: "users/999",
|
14
|
+
first_name: "Badger",
|
15
|
+
last_name: "Smith",
|
16
|
+
email: "b@smith.biz",
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
let(:no_parameters_factory) {
|
21
|
+
->() { }
|
22
|
+
}
|
23
|
+
|
24
|
+
it "raises a helpful error message" do
|
25
|
+
error = nil
|
26
|
+
begin
|
27
|
+
load_first_user
|
28
|
+
rescue Terrestrial::Error => error
|
29
|
+
end
|
30
|
+
|
31
|
+
expect(error.message).to eq(
|
32
|
+
[
|
33
|
+
"Error loading record from `users` relation `#{record.inspect}`.",
|
34
|
+
"Using: `#{no_parameters_factory.inspect}`.",
|
35
|
+
"Check that the factory is compatible.",
|
36
|
+
"Got Error: ArgumentError wrong number of arguments (given 1, expected 0)",
|
37
|
+
].join("\n")
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_first_user
|
43
|
+
@object_store[:users].first
|
44
|
+
end
|
45
|
+
|
46
|
+
def override_user_factory_with(factory)
|
47
|
+
config = Terrestrial.config(datastore)
|
48
|
+
.setup_mapping(:users) { |users|
|
49
|
+
users.factory(factory)
|
50
|
+
}
|
51
|
+
|
52
|
+
@object_store = Terrestrial.object_store(
|
53
|
+
mappings: config,
|
54
|
+
datastore: datastore,
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def seed_user(record)
|
59
|
+
datastore[:users].insert(record)
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "support/object_store_setup"
|
2
|
+
|
3
|
+
RSpec.describe "Serialization error handling" do
|
4
|
+
include_context "object store setup"
|
5
|
+
context "when a domain object is incompatible with its serializer" do
|
6
|
+
before do
|
7
|
+
override_user_serializer_with(incompatible_custom_serializer)
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:user) { Object.new }
|
11
|
+
|
12
|
+
let(:incompatible_custom_serializer) {
|
13
|
+
->(x) { raise "I am incompatible" }
|
14
|
+
}
|
15
|
+
|
16
|
+
it "rescues and re-raises a more detailed error" do
|
17
|
+
error = nil
|
18
|
+
begin
|
19
|
+
save_user
|
20
|
+
rescue Terrestrial::SerializationError => error
|
21
|
+
end
|
22
|
+
|
23
|
+
expect(error.message).to eq(
|
24
|
+
[
|
25
|
+
"Error serializing object with mapping `users` `#{user.inspect}`.",
|
26
|
+
"Using serializer: `#{incompatible_custom_serializer.inspect}`.",
|
27
|
+
"Check the specified serializer can transform objects into a Hash.",
|
28
|
+
"Got Error: RuntimeError I am incompatible",
|
29
|
+
].join("\n")
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
# TODO: make configuration easier override
|
34
|
+
def override_user_serializer_with(serializer)
|
35
|
+
config = Terrestrial.config(datastore)
|
36
|
+
.setup_mapping(:users) { |users|
|
37
|
+
users.serializer(serializer)
|
38
|
+
}
|
39
|
+
|
40
|
+
@object_store = Terrestrial.object_store(
|
41
|
+
mappings: config,
|
42
|
+
datastore: datastore,
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def save_user
|
47
|
+
@object_store[:users].save(user)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require "support/object_store_setup"
|
2
|
+
require "terrestrial/inspection_string"
|
3
|
+
|
4
|
+
RSpec.describe "Upsert error handling" do
|
5
|
+
include_context "object store setup"
|
6
|
+
let(:user) { double(:user) }
|
7
|
+
|
8
|
+
context "with an record that raises error on persistence" do
|
9
|
+
before do
|
10
|
+
use_custom_serializer( ->(_) { unpersistable_record } )
|
11
|
+
end
|
12
|
+
let(:unpersistable_record) { UnpersistableRecord.new(original_error) }
|
13
|
+
let(:original_error) { RuntimeError.new("Cannot upsert") }
|
14
|
+
|
15
|
+
it "raises an UpsertError with detail of the original error" do
|
16
|
+
error = nil
|
17
|
+
begin
|
18
|
+
save_user
|
19
|
+
rescue Terrestrial::UpsertError => error
|
20
|
+
end
|
21
|
+
|
22
|
+
expect(error.message).to eq(
|
23
|
+
[
|
24
|
+
"Error upserting record into `users` with data `#{unpersistable_record}`.",
|
25
|
+
"Got Error: #{original_error.class} #{original_error.message}",
|
26
|
+
].join("\n")
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class UnpersistableRecord
|
32
|
+
include Terrestrial::InspectionString
|
33
|
+
|
34
|
+
def initialize(error)
|
35
|
+
@error = error
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_h
|
39
|
+
# This is used in error reporting
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_missing(*_)
|
44
|
+
# Raising on anything else ensures a problem while persisting
|
45
|
+
raise_if_upserting
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def raise_if_upserting
|
52
|
+
raise(@error) if caller.any? { |line| /if_upsert/ === line }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "serializer returns an extra field not in the schema" do
|
57
|
+
before do
|
58
|
+
use_custom_serializer(extra_field_serializer)
|
59
|
+
end
|
60
|
+
|
61
|
+
let(:extra_field_serializer) {
|
62
|
+
->(_x) {
|
63
|
+
{
|
64
|
+
extra_field_that_does_not_match_column: "some value",
|
65
|
+
id: "users/999",
|
66
|
+
first_name: "Hansel",
|
67
|
+
last_name: "Trickett",
|
68
|
+
email: "hansel@tricketts.org",
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
it "filters the serialization result and raises no error" do
|
74
|
+
expect { save_user }.not_to raise_error
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "serialization result omits required fields" do
|
79
|
+
before do
|
80
|
+
use_custom_serializer(missing_id_serializer)
|
81
|
+
end
|
82
|
+
|
83
|
+
let(:missing_id_serializer) {
|
84
|
+
->(_x) { serialization_result }
|
85
|
+
}
|
86
|
+
|
87
|
+
let(:serialization_result) {
|
88
|
+
object_attributes.reject { |k,v| k == :id }
|
89
|
+
}
|
90
|
+
|
91
|
+
let(:object_attributes) {
|
92
|
+
{
|
93
|
+
id: "users/999",
|
94
|
+
first_name: "Hansel",
|
95
|
+
last_name: "Trickett",
|
96
|
+
email: "hansel@tricketts.org",
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
it "raises an UpsertError with detail of the original error", backend: "sequel" do
|
101
|
+
error = nil
|
102
|
+
begin
|
103
|
+
save_user
|
104
|
+
rescue Terrestrial::UpsertError => error
|
105
|
+
end
|
106
|
+
|
107
|
+
expect(error.message).to eq(
|
108
|
+
[
|
109
|
+
"Error upserting record into `users` with data `#{serialization_result}`.",
|
110
|
+
"Got Error: Sequel::NotNullConstraintViolation PG::NotNullViolation: ERROR: null value in column \"id\" violates not-null constraint",
|
111
|
+
"DETAIL: Failing row contains (null, Hansel, Trickett, hansel@tricketts.org).\n",
|
112
|
+
].join("\n")
|
113
|
+
)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def save_user
|
118
|
+
@object_store[:users].save(user)
|
119
|
+
end
|
120
|
+
|
121
|
+
def use_custom_serializer(serializer)
|
122
|
+
config = Terrestrial.config(datastore)
|
123
|
+
.setup_mapping(:users) { |users|
|
124
|
+
users.serializer(serializer)
|
125
|
+
}
|
126
|
+
|
127
|
+
@object_store = Terrestrial.object_store(
|
128
|
+
mappings: config,
|
129
|
+
datastore: datastore,
|
130
|
+
)
|
131
|
+
end
|
132
|
+
end
|