vorpal 0.0.6.rc2 → 0.0.6.rc3
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 +8 -8
- data/lib/vorpal/aggregate_repository.rb +31 -56
- data/lib/vorpal/configs.rb +208 -198
- data/lib/vorpal/configuration.rb +15 -4
- data/lib/vorpal/db_driver.rb +33 -35
- data/lib/vorpal/db_loader.rb +29 -17
- data/lib/vorpal/identity_map.rb +0 -4
- data/lib/vorpal/loaded_objects.rb +8 -21
- data/lib/vorpal/util/array_hash.rb +10 -4
- data/lib/vorpal/version.rb +1 -1
- data/spec/helpers/db_helpers.rb +18 -0
- data/spec/integration_spec_helper.rb +4 -0
- data/spec/vorpal/aggregate_repository_spec.rb +5 -70
- data/spec/vorpal/configs_spec.rb +107 -0
- data/spec/vorpal/performance_spec.rb +192 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NDJjYTFiMjk0N2U4NmYxYjI4NGIwMmY0N2VkOWZiYjRjZjI4OTFlOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OWJjZDM0Y2JiMGIzNGNlY2MxOWFmNDQwYWUyZTRiMDJiNDBkNmZmYw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NmU3YTQ2OGNkYzZjNTM3ODMxODc5NjlhZjFhOWFlMmNkMjRmMzg1NGE0ZGRm
|
10
|
+
MGY3MWRlZjM0ZjFlOWFhNzI0N2Q2MzMwODMyYzFkODJlMzExZjBmZTAzNGE0
|
11
|
+
NmUzODFkMWU3M2IzN2NhODA3YzZhMDU1OTllZjEyNzJlY2Q0ODI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MWY5NzQ0N2Q2NjE5NDI4MmE4MzRmMDM4ZjI3M2M4NjQ1MTBhYzA4MWY3YTJm
|
14
|
+
YmQxNDI2MTcwOWRkYmRlNjcwYTNiN2E4N2I1ZWU4ZmZiYTZkMWU1ZDE2NmZh
|
15
|
+
NjA0OWJmMDg2Y2M4NDYzYzVhNjg5MTE0YTAzMTg4NDkzOTNmNTQ=
|
@@ -6,8 +6,9 @@ require 'vorpal/db_driver'
|
|
6
6
|
module Vorpal
|
7
7
|
class AggregateRepository
|
8
8
|
# @private
|
9
|
-
def initialize(
|
10
|
-
|
9
|
+
def initialize(db_driver, master_config)
|
10
|
+
@db_driver = db_driver
|
11
|
+
@configs = master_config
|
11
12
|
end
|
12
13
|
|
13
14
|
# Saves an aggregate to the DB. Inserts objects that are new to the
|
@@ -76,11 +77,11 @@ class AggregateRepository
|
|
76
77
|
# operation.
|
77
78
|
# @return [[Object]] Entities with the given primary key values and type.
|
78
79
|
def load_all(ids, domain_class, identity_map=IdentityMap.new)
|
79
|
-
|
80
|
-
deserialize(
|
81
|
-
set_associations(
|
80
|
+
loaded_db_objects = load_from_db(ids, domain_class)
|
81
|
+
objects = deserialize(loaded_db_objects, identity_map)
|
82
|
+
set_associations(loaded_db_objects, identity_map)
|
82
83
|
|
83
|
-
|
84
|
+
objects.select { |obj| obj.class == domain_class }
|
84
85
|
end
|
85
86
|
|
86
87
|
# Removes an aggregate from the DB. Even if the aggregate contains unsaved
|
@@ -101,7 +102,7 @@ class AggregateRepository
|
|
101
102
|
return roots if roots.empty?
|
102
103
|
loaded_db_objects = load_owned_from_db(roots.map(&:id), roots.first.class)
|
103
104
|
loaded_db_objects.each do |config, db_objects|
|
104
|
-
|
105
|
+
@db_driver.destroy(config.db_class, db_objects)
|
105
106
|
end
|
106
107
|
roots
|
107
108
|
end
|
@@ -113,62 +114,36 @@ class AggregateRepository
|
|
113
114
|
end
|
114
115
|
|
115
116
|
def load_from_db(ids, domain_class, only_owned=false)
|
116
|
-
DbLoader.new(@configs, only_owned).load_from_db(ids, domain_class)
|
117
|
+
DbLoader.new(@configs, only_owned, @db_driver).load_from_db(ids, domain_class)
|
117
118
|
end
|
118
119
|
|
119
120
|
def load_owned_from_db(ids, domain_class)
|
120
121
|
load_from_db(ids, domain_class, true)
|
121
122
|
end
|
122
123
|
|
123
|
-
def deserialize(
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
|
-
def set_associations(db_objects, identity_map)
|
131
|
-
db_objects.each do |db_object|
|
132
|
-
config = @configs.config_for_db(db_object.class)
|
133
|
-
config.has_manys.each do |has_many_config|
|
134
|
-
db_children = find_associated(db_object, has_many_config, db_objects)
|
135
|
-
associate_one_to_many(db_object, db_children, has_many_config, identity_map)
|
136
|
-
end
|
137
|
-
|
138
|
-
config.has_ones.each do |has_one_config|
|
139
|
-
db_children = find_associated(db_object, has_one_config, db_objects)
|
140
|
-
associate_one_to_one(db_object, db_children.first, has_one_config, identity_map)
|
141
|
-
end
|
142
|
-
|
143
|
-
config.belongs_tos.each do |belongs_to_config|
|
144
|
-
db_children = find_associated(db_object, belongs_to_config, db_objects)
|
145
|
-
associate_one_to_one(db_object, db_children.first, belongs_to_config, identity_map)
|
124
|
+
def deserialize(loaded_db_objects, identity_map)
|
125
|
+
loaded_db_objects.flat_map do |config, db_objects|
|
126
|
+
db_objects.map do |db_object|
|
127
|
+
# TODO: There is a bug here when you have something in the IdentityMap that is stale and needs to be updated.
|
128
|
+
identity_map.get_and_set(db_object) { config.deserialize(db_object) }
|
146
129
|
end
|
147
130
|
end
|
148
131
|
end
|
149
132
|
|
150
|
-
def
|
151
|
-
|
152
|
-
|
133
|
+
def set_associations(loaded_db_objects, identity_map)
|
134
|
+
loaded_db_objects.each do |config, db_objects|
|
135
|
+
db_objects.each do |db_object|
|
136
|
+
config.local_association_configs.each do |association_config|
|
137
|
+
db_remote = loaded_db_objects.find_by_id(
|
138
|
+
association_config.remote_class_config(db_object),
|
139
|
+
association_config.fk_value(db_object)
|
140
|
+
)
|
141
|
+
association_config.associate(identity_map.get(db_object), identity_map.get(db_remote))
|
142
|
+
end
|
143
|
+
end
|
153
144
|
end
|
154
145
|
end
|
155
146
|
|
156
|
-
def associate_one_to_many(db_object, db_children, one_to_many, identity_map)
|
157
|
-
parent = identity_map.get(db_object)
|
158
|
-
children = identity_map.map(db_children)
|
159
|
-
one_to_many.set_children(parent, children)
|
160
|
-
end
|
161
|
-
|
162
|
-
def associate_one_to_one(db_parent, db_child, one_to_one_config, identity_map)
|
163
|
-
parent = identity_map.get(db_parent)
|
164
|
-
child = identity_map.get(db_child)
|
165
|
-
one_to_one_config.set_child(parent, child)
|
166
|
-
end
|
167
|
-
|
168
|
-
def configure(class_configs)
|
169
|
-
@configs = MasterConfig.new(class_configs)
|
170
|
-
end
|
171
|
-
|
172
147
|
def serialize(owned_objects, mapping, loaded_db_objects)
|
173
148
|
owned_objects.each do |config, objects|
|
174
149
|
objects.each do |object|
|
@@ -184,7 +159,7 @@ class AggregateRepository
|
|
184
159
|
if object.id.nil?
|
185
160
|
config.build_db_object(attributes)
|
186
161
|
else
|
187
|
-
db_object = loaded_db_objects.find_by_id(
|
162
|
+
db_object = loaded_db_objects.find_by_id(config, object.id)
|
188
163
|
config.set_db_object_attributes(db_object, attributes)
|
189
164
|
db_object
|
190
165
|
end
|
@@ -196,7 +171,7 @@ class AggregateRepository
|
|
196
171
|
def set_primary_keys(owned_objects, mapping)
|
197
172
|
owned_objects.each do |config, objects|
|
198
173
|
in_need_of_primary_keys = objects.find_all { |obj| obj.id.nil? }
|
199
|
-
primary_keys =
|
174
|
+
primary_keys = @db_driver.get_primary_keys(config.db_class, in_need_of_primary_keys.length)
|
200
175
|
in_need_of_primary_keys.zip(primary_keys).each do |object, primary_key|
|
201
176
|
mapping[object].id = primary_key
|
202
177
|
object.id = primary_key
|
@@ -237,11 +212,11 @@ class AggregateRepository
|
|
237
212
|
owned_objects.each do |config, objects|
|
238
213
|
objects_to_insert = grouped_new_objects[config] || []
|
239
214
|
db_objects_to_insert = objects_to_insert.map { |obj| mapping[obj] }
|
240
|
-
|
215
|
+
@db_driver.insert(config.db_class, db_objects_to_insert)
|
241
216
|
|
242
217
|
objects_to_update = objects - objects_to_insert
|
243
218
|
db_objects_to_update = objects_to_update.map { |obj| mapping[obj] }
|
244
|
-
|
219
|
+
@db_driver.update(config.db_class, db_objects_to_update)
|
245
220
|
end
|
246
221
|
end
|
247
222
|
|
@@ -249,9 +224,9 @@ class AggregateRepository
|
|
249
224
|
db_objects_in_aggregate = mapping.values
|
250
225
|
db_objects_in_db = loaded_db_objects.all_objects
|
251
226
|
all_orphans = db_objects_in_db - db_objects_in_aggregate
|
252
|
-
grouped_orphans = all_orphans.group_by { |o| @configs.
|
227
|
+
grouped_orphans = all_orphans.group_by { |o| @configs.config_for_db_object(o) }
|
253
228
|
grouped_orphans.each do |config, orphans|
|
254
|
-
|
229
|
+
@db_driver.destroy(config.db_class, orphans)
|
255
230
|
end
|
256
231
|
end
|
257
232
|
|
data/lib/vorpal/configs.rb
CHANGED
@@ -2,268 +2,278 @@ require 'vorpal/util/hash_initialization'
|
|
2
2
|
require 'equalizer'
|
3
3
|
|
4
4
|
module Vorpal
|
5
|
+
# @private
|
6
|
+
class MasterConfig
|
7
|
+
def initialize(class_configs)
|
8
|
+
@class_configs = class_configs
|
9
|
+
initialize_association_configs
|
10
|
+
end
|
5
11
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@class_configs = class_configs
|
10
|
-
initialize_association_configs
|
11
|
-
end
|
12
|
-
|
13
|
-
def config_for(clazz)
|
14
|
-
@class_configs.detect { |conf| conf.domain_class == clazz }
|
15
|
-
end
|
12
|
+
def config_for(clazz)
|
13
|
+
@class_configs.detect { |conf| conf.domain_class == clazz }
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def config_for_db_object(db_object)
|
17
|
+
@class_configs.detect { |conf| conf.db_class == db_object.class }
|
18
|
+
end
|
20
19
|
|
21
|
-
|
20
|
+
private
|
21
|
+
|
22
|
+
def initialize_association_configs
|
23
|
+
association_configs = {}
|
24
|
+
@class_configs.each do |config|
|
25
|
+
(config.has_ones + config.has_manys).each do |association_end_config|
|
26
|
+
child_config = config_for(association_end_config.child_class)
|
27
|
+
association_end_config.set_parent_class_config(config)
|
28
|
+
|
29
|
+
association_config = build_association_config(association_configs, child_config, association_end_config.fk, association_end_config.fk_type)
|
30
|
+
association_config.remote_end_config = association_end_config
|
31
|
+
association_config.add_remote_class_config(config)
|
32
|
+
association_end_config.association_config = association_config
|
33
|
+
end
|
34
|
+
|
35
|
+
config.belongs_tos.each do |association_end_config|
|
36
|
+
child_configs = association_end_config.child_classes.map(&method(:config_for))
|
37
|
+
|
38
|
+
association_config = build_association_config(association_configs, config, association_end_config.fk, association_end_config.fk_type)
|
39
|
+
association_config.local_end_config = association_end_config
|
40
|
+
association_config.add_remote_class_config(child_configs)
|
41
|
+
association_end_config.association_config = association_config
|
42
|
+
end
|
43
|
+
end
|
22
44
|
|
23
|
-
|
24
|
-
|
25
|
-
(config.has_ones + config.has_manys).each do |association_config|
|
26
|
-
association_config.init_relational_association(
|
27
|
-
config_for(association_config.child_class),
|
28
|
-
config
|
29
|
-
)
|
45
|
+
association_configs.values.each do |association_config|
|
46
|
+
association_config.local_class_config.local_association_configs << association_config
|
30
47
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_association_config(association_configs, local_config, fk, fk_type)
|
51
|
+
association_config = AssociationConfig.new(local_config, fk, fk_type)
|
52
|
+
if association_configs[association_config]
|
53
|
+
association_config = association_configs[association_config]
|
54
|
+
else
|
55
|
+
association_configs[association_config] = association_config
|
36
56
|
end
|
57
|
+
association_config
|
37
58
|
end
|
38
59
|
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# @private
|
42
|
-
class ClassConfig
|
43
|
-
include Equalizer.new(:domain_class, :db_class)
|
44
|
-
attr_reader :serializer, :deserializer, :domain_class, :db_class
|
45
|
-
attr_accessor :has_manys, :belongs_tos, :has_ones
|
46
60
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
61
|
+
# @private
|
62
|
+
# Object associations:
|
63
|
+
# - All object associations are uni-directional
|
64
|
+
# - The end that holds the association is the 'Parent' and the end that
|
65
|
+
# is referred to is the 'Child' or 'Children'
|
66
|
+
#
|
67
|
+
# Relational associations:
|
68
|
+
# - Local end: has FK
|
69
|
+
# - Remote end: has no FK
|
70
|
+
#
|
71
|
+
class AssociationConfig
|
72
|
+
include Equalizer.new(:local_class_config, :fk)
|
73
|
+
|
74
|
+
attr_reader :local_class_config, :remote_class_configs, :fk
|
75
|
+
|
76
|
+
# Only one of these two fields needs to be specified
|
77
|
+
# If one is specified, then the association is uni-directional.
|
78
|
+
# If both are specified, then the association is bi-directional.
|
79
|
+
attr_accessor :local_end_config, :remote_end_config
|
80
|
+
|
81
|
+
def initialize(local_class_config, fk, fk_type)
|
82
|
+
@local_class_config = local_class_config
|
83
|
+
@remote_class_configs = {}
|
84
|
+
@fk = fk
|
85
|
+
@fk_type = fk_type
|
54
86
|
end
|
55
|
-
end
|
56
87
|
|
57
|
-
|
58
|
-
|
59
|
-
|
88
|
+
def fk_value(local_db_object)
|
89
|
+
local_db_object.send(fk)
|
90
|
+
end
|
60
91
|
|
61
|
-
|
62
|
-
|
63
|
-
|
92
|
+
def associate(local_object, remote_object)
|
93
|
+
local_end_config.associate(local_object, remote_object) if local_end_config && local_object
|
94
|
+
remote_end_config.associate(remote_object, local_object) if remote_end_config && remote_object
|
95
|
+
end
|
64
96
|
|
65
|
-
|
66
|
-
|
67
|
-
|
97
|
+
def add_remote_class_config(remote_class_configs)
|
98
|
+
Array(remote_class_configs).each do |remote_class_config|
|
99
|
+
@remote_class_configs[remote_class_config.domain_class.name] = remote_class_config
|
100
|
+
end
|
101
|
+
end
|
68
102
|
|
69
|
-
|
70
|
-
|
71
|
-
|
103
|
+
def remote_class_config(local_db_object)
|
104
|
+
if polymorphic?
|
105
|
+
fk_type_value = local_db_object.send(@fk_type)
|
106
|
+
@remote_class_configs[fk_type_value]
|
107
|
+
else
|
108
|
+
@remote_class_configs.values.first
|
109
|
+
end
|
110
|
+
end
|
72
111
|
|
73
|
-
|
74
|
-
|
75
|
-
|
112
|
+
def polymorphic?
|
113
|
+
!@fk_type.nil?
|
114
|
+
end
|
76
115
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
116
|
+
def set_foreign_key(local_db_object, remote_object)
|
117
|
+
local_class_config.set_field(local_db_object, @fk, remote_object.try(:id))
|
118
|
+
local_class_config.set_field(local_db_object, @fk_type, remote_object.class.name) if polymorphic?
|
119
|
+
end
|
81
120
|
|
82
|
-
|
83
|
-
|
121
|
+
def foreign_key_info(remote_class_config)
|
122
|
+
ForeignKeyInfo.new(@fk, @fk_type, remote_class_config.domain_class.name, polymorphic?)
|
123
|
+
end
|
84
124
|
end
|
85
125
|
|
86
|
-
|
87
|
-
|
88
|
-
|
126
|
+
# @private
|
127
|
+
class ClassConfig
|
128
|
+
include Equalizer.new(:domain_class, :db_class)
|
129
|
+
attr_reader :serializer, :deserializer, :domain_class, :db_class, :local_association_configs
|
130
|
+
attr_accessor :has_manys, :belongs_tos, :has_ones
|
89
131
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
132
|
+
def initialize(attrs)
|
133
|
+
@has_manys = []
|
134
|
+
@belongs_tos = []
|
135
|
+
@has_ones = []
|
136
|
+
@local_association_configs = []
|
94
137
|
|
95
|
-
|
96
|
-
|
97
|
-
|
138
|
+
attrs.each do |k,v|
|
139
|
+
instance_variable_set("@#{k}", v)
|
140
|
+
end
|
141
|
+
end
|
98
142
|
|
99
|
-
|
143
|
+
def build_db_object(attributes)
|
144
|
+
db_class.new(attributes)
|
145
|
+
end
|
100
146
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
@fk_type = fk_type
|
105
|
-
@polymorphic = polymorphic
|
106
|
-
end
|
147
|
+
def set_db_object_attributes(db_object, attributes)
|
148
|
+
db_object.attributes = attributes
|
149
|
+
end
|
107
150
|
|
108
|
-
|
109
|
-
|
110
|
-
|
151
|
+
def get_db_object_attributes(db_object)
|
152
|
+
db_object.attributes.symbolize_keys
|
153
|
+
end
|
111
154
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
155
|
+
def serialization_required?
|
156
|
+
!(domain_class < ActiveRecord::Base)
|
157
|
+
end
|
116
158
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
# - The end that holds the association is the 'Parent' and the end that
|
121
|
-
# is referred to is the 'Child' or 'Children'
|
122
|
-
#
|
123
|
-
# Relational associations:
|
124
|
-
# - Local end: has FK
|
125
|
-
# - Remote end: has no FK
|
126
|
-
#
|
127
|
-
class RelationalAssociation
|
128
|
-
include HashInitialization
|
129
|
-
attr_reader :fk, :fk_type, :local_config, :remote_configs
|
130
|
-
|
131
|
-
# Can't pass in a remote db model for last param because when saving we only have
|
132
|
-
# a db model if the model is part of the aggregate and not just referenced by the
|
133
|
-
# aggregate
|
134
|
-
def set_foreign_key(local_db_model, remote_model)
|
135
|
-
local_config.set_field(local_db_model, fk, remote_model.try(:id))
|
136
|
-
local_config.set_field(local_db_model, fk_type, remote_model.class.name) if polymorphic?
|
137
|
-
end
|
159
|
+
def serialize(object)
|
160
|
+
serializer.serialize(object)
|
161
|
+
end
|
138
162
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
163
|
+
def deserialize(db_object)
|
164
|
+
attributes = get_db_object_attributes(db_object)
|
165
|
+
serialization_required? ? deserializer.deserialize(domain_class.new, attributes) : db_object
|
166
|
+
end
|
143
167
|
|
144
|
-
|
145
|
-
|
146
|
-
|
168
|
+
def set_field(db_object, field, value)
|
169
|
+
db_object.send("#{field}=", value)
|
170
|
+
end
|
147
171
|
|
148
|
-
|
149
|
-
|
172
|
+
def get_field(db_object, field)
|
173
|
+
db_object.send(field)
|
174
|
+
end
|
150
175
|
end
|
151
176
|
|
152
|
-
private
|
177
|
+
# @private
|
178
|
+
class ForeignKeyInfo
|
179
|
+
include Equalizer.new(:fk_column, :fk_type_column, :fk_type)
|
153
180
|
|
154
|
-
|
155
|
-
local_config.get_field(local_db_model, fk)
|
156
|
-
end
|
157
|
-
end
|
181
|
+
attr_reader :fk_column, :fk_type_column, :fk_type, :polymorphic
|
158
182
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
183
|
+
def initialize(fk_column, fk_type_column, fk_type, polymorphic)
|
184
|
+
@fk_column = fk_column
|
185
|
+
@fk_type_column = fk_type_column
|
186
|
+
@fk_type = fk_type
|
187
|
+
@polymorphic = polymorphic
|
188
|
+
end
|
163
189
|
|
164
|
-
|
165
|
-
|
166
|
-
|
190
|
+
def polymorphic?
|
191
|
+
@polymorphic
|
192
|
+
end
|
167
193
|
end
|
168
194
|
|
169
|
-
|
170
|
-
|
171
|
-
|
195
|
+
module RemoteEndConfig
|
196
|
+
def child_config
|
197
|
+
association_config.local_class_config
|
198
|
+
end
|
172
199
|
|
173
|
-
|
174
|
-
|
175
|
-
|
200
|
+
def set_foreign_key(db_child, parent)
|
201
|
+
association_config.set_foreign_key(db_child, parent)
|
202
|
+
end
|
176
203
|
|
177
|
-
|
178
|
-
|
179
|
-
|
204
|
+
def set_parent_class_config(parent_config)
|
205
|
+
@parent_config = parent_config
|
206
|
+
end
|
180
207
|
|
181
|
-
|
182
|
-
|
183
|
-
|
208
|
+
def foreign_key_info
|
209
|
+
association_config.foreign_key_info(@parent_config)
|
210
|
+
end
|
184
211
|
end
|
185
212
|
|
186
|
-
|
187
|
-
|
188
|
-
|
213
|
+
module LocalEndConfig
|
214
|
+
def child_config(db_parent)
|
215
|
+
association_config.remote_class_config(db_parent)
|
216
|
+
end
|
189
217
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
end
|
194
|
-
# @private
|
195
|
-
class BelongsToConfig
|
196
|
-
include HashInitialization
|
197
|
-
attr_reader :name, :owned, :fk, :fk_type, :child_classes
|
218
|
+
def set_foreign_key(db_parent, child)
|
219
|
+
association_config.set_foreign_key(db_parent, child)
|
220
|
+
end
|
198
221
|
|
199
|
-
def
|
200
|
-
|
222
|
+
def fk_value(db_parent)
|
223
|
+
db_parent.send(fk)
|
201
224
|
end
|
225
|
+
end
|
202
226
|
|
227
|
+
module ToOneConfig
|
203
228
|
def get_child(parent)
|
204
229
|
parent.send(name)
|
205
230
|
end
|
206
231
|
|
207
|
-
def
|
232
|
+
def associate(parent, child)
|
208
233
|
parent.send("#{name}=", child)
|
209
234
|
end
|
235
|
+
end
|
210
236
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
def associated?(db_parent, db_child)
|
216
|
-
return false if child_config(db_parent).db_class != db_child.class
|
217
|
-
fk_value(db_parent) == db_child.id
|
237
|
+
module ToManyConfig
|
238
|
+
def get_children(parent)
|
239
|
+
parent.send(name)
|
218
240
|
end
|
219
241
|
|
220
|
-
def
|
221
|
-
if
|
222
|
-
|
223
|
-
else
|
224
|
-
@relational_association.remote_configs.first
|
242
|
+
def associate(parent, child)
|
243
|
+
if get_children(parent).nil?
|
244
|
+
parent.send("#{name}=", [])
|
225
245
|
end
|
246
|
+
get_children(parent) << child
|
226
247
|
end
|
227
|
-
|
228
|
-
def fk_value(db_parent)
|
229
|
-
db_parent.send(fk)
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
# @private
|
234
|
-
class HasOneConfig
|
235
|
-
include HashInitialization
|
236
|
-
attr_reader :name, :owned, :fk, :fk_type, :child_class
|
237
|
-
|
238
|
-
def init_relational_association(child_config, parent_config)
|
239
|
-
@parent_config = parent_config
|
240
|
-
@relational_association = RelationalAssociation.new(fk: fk, fk_type: fk_type, local_config: child_config, remote_configs: [parent_config])
|
241
248
|
end
|
242
249
|
|
243
|
-
|
244
|
-
|
245
|
-
|
250
|
+
# @private
|
251
|
+
class HasManyConfig
|
252
|
+
include HashInitialization
|
253
|
+
include RemoteEndConfig
|
254
|
+
include ToManyConfig
|
246
255
|
|
247
|
-
|
248
|
-
|
256
|
+
attr_reader :name, :owned, :fk, :fk_type, :child_class
|
257
|
+
attr_accessor :association_config
|
249
258
|
end
|
250
259
|
|
251
|
-
|
252
|
-
|
253
|
-
|
260
|
+
# @private
|
261
|
+
class BelongsToConfig
|
262
|
+
include HashInitialization
|
263
|
+
include LocalEndConfig
|
264
|
+
include ToOneConfig
|
254
265
|
|
255
|
-
|
256
|
-
|
257
|
-
db_child.send(fk) == db_parent.id
|
266
|
+
attr_reader :name, :owned, :fk, :fk_type, :child_classes
|
267
|
+
attr_accessor :association_config
|
258
268
|
end
|
259
269
|
|
260
|
-
|
261
|
-
|
262
|
-
|
270
|
+
# @private
|
271
|
+
class HasOneConfig
|
272
|
+
include HashInitialization
|
273
|
+
include RemoteEndConfig
|
274
|
+
include ToOneConfig
|
263
275
|
|
264
|
-
|
265
|
-
|
276
|
+
attr_reader :name, :owned, :fk, :fk_type, :child_class
|
277
|
+
attr_accessor :association_config
|
266
278
|
end
|
267
279
|
end
|
268
|
-
|
269
|
-
end
|