rom-core 4.0.0.beta3 → 4.0.0.rc1
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 +3 -1
- data/lib/rom/association_set.rb +3 -0
- data/lib/rom/associations/abstract.rb +72 -1
- data/lib/rom/associations/definitions/abstract.rb +22 -6
- data/lib/rom/associations/definitions/many_to_many.rb +3 -0
- data/lib/rom/associations/definitions/many_to_one.rb +1 -0
- data/lib/rom/associations/definitions/one_to_many.rb +1 -0
- data/lib/rom/associations/definitions/one_to_one.rb +1 -0
- data/lib/rom/associations/definitions/one_to_one_through.rb +1 -0
- data/lib/rom/associations/many_to_many.rb +44 -0
- data/lib/rom/associations/many_to_one.rb +26 -0
- data/lib/rom/associations/one_to_many.rb +26 -0
- data/lib/rom/associations/one_to_one.rb +3 -0
- data/lib/rom/associations/one_to_one_through.rb +3 -0
- data/lib/rom/attribute.rb +2 -2
- data/lib/rom/auto_curry.rb +11 -0
- data/lib/rom/cache.rb +29 -0
- data/lib/rom/command_compiler.rb +4 -4
- data/lib/rom/command_registry.rb +9 -5
- data/lib/rom/commands/class_interface.rb +7 -7
- data/lib/rom/commands/graph/input_evaluator.rb +33 -3
- data/lib/rom/commands/lazy.rb +4 -0
- data/lib/rom/commands/lazy/create.rb +10 -0
- data/lib/rom/commands/lazy/delete.rb +10 -0
- data/lib/rom/commands/lazy/update.rb +10 -0
- data/lib/rom/configuration.rb +34 -14
- data/lib/rom/configuration_dsl.rb +0 -2
- data/lib/rom/constants.rb +10 -0
- data/lib/rom/container.rb +16 -0
- data/lib/rom/create_container.rb +7 -0
- data/lib/rom/environment.rb +3 -2
- data/lib/rom/gateway.rb +16 -1
- data/lib/rom/global.rb +1 -1
- data/lib/rom/global/plugin_dsl.rb +3 -1
- data/lib/rom/initializer.rb +25 -13
- data/lib/rom/mapper_registry.rb +4 -1
- data/lib/rom/memory/dataset.rb +29 -2
- data/lib/rom/memory/schema.rb +7 -0
- data/lib/rom/plugin_base.rb +1 -1
- data/lib/rom/plugin_registry.rb +2 -2
- data/lib/rom/plugins/command/schema.rb +7 -0
- data/lib/rom/plugins/relation/instrumentation.rb +10 -0
- data/lib/rom/plugins/relation/registry_reader.rb +0 -3
- data/lib/rom/registry.rb +15 -3
- data/lib/rom/relation.rb +38 -23
- data/lib/rom/relation/class_interface.rb +15 -6
- data/lib/rom/relation/combined.rb +7 -2
- data/lib/rom/relation/curried.rb +23 -0
- data/lib/rom/relation/graph.rb +25 -14
- data/lib/rom/relation/loaded.rb +7 -4
- data/lib/rom/relation/materializable.rb +2 -2
- data/lib/rom/relation/view_dsl.rb +2 -1
- data/lib/rom/relation/wrap.rb +14 -0
- data/lib/rom/relation_registry.rb +2 -0
- data/lib/rom/schema.rb +25 -4
- data/lib/rom/schema/associations_dsl.rb +9 -0
- data/lib/rom/schema/dsl.rb +27 -4
- data/lib/rom/setup.rb +20 -7
- data/lib/rom/setup/auto_registration.rb +27 -0
- data/lib/rom/setup/auto_registration_strategies/base.rb +7 -2
- data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +17 -0
- data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +11 -0
- data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +9 -0
- data/lib/rom/setup/finalize/finalize_mappers.rb +4 -2
- data/lib/rom/setup/finalize/finalize_relations.rb +1 -1
- data/lib/rom/support/configurable.rb +19 -0
- data/lib/rom/support/notifications.rb +29 -2
- data/lib/rom/types.rb +53 -8
- data/lib/rom/version.rb +1 -1
- metadata +7 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd842da91b8eff4e935f9bc0064b7225fbc41d6a
|
4
|
+
data.tar.gz: b949c0798bbddfb9bb49b52b0e4137759accc1f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c95c856d8c205db0013f905ad72e4e8bcecc243f227410d05607c8e2f1280e5d7cf8943c607cd6b45f5926e55e8febadab4e809cb847efe3e96c48e8c4873200
|
7
|
+
data.tar.gz: bf2277dae18e48950740d93a6478cf4d0d56eda97065b797edb5d88d8ab9327f871ab99d2207a909ae80663ae0a654b2495485be7ddf071ab5da6105737b9db8
|
data/CHANGELOG.md
CHANGED
@@ -12,8 +12,10 @@ Previous `rom` gem was renamed to `rom-core`
|
|
12
12
|
* `Relation#command` which automatically creates a command for a given relation, supports graphs too (solnic)
|
13
13
|
* `Relation::to_ast` which returns an AST representation of a relation. This can be used to infer other objects based on relation information (solnic)
|
14
14
|
* `Relation::Name#as` which returns an aliased relation name (solnic)
|
15
|
-
* Association DSL supports `:override` option which will use configured `:view` as the relation used by association (solnic)
|
16
15
|
* Associations are now part of core API and available to all adapters, cross-adapter associations are supported too via `:override` option (solnic)
|
16
|
+
* New settings in association DSL:
|
17
|
+
* `:override` option which will use configured `:view` as the relation used by association (solnic)
|
18
|
+
* `:combine_keys` option which overriddes default combine keys that are based on join keys (solnic)
|
17
19
|
* `Schema#primary_key_name` and `Schema#primary_key_names` are now part of core schema API (solnic)
|
18
20
|
* `Schema#to_ast` which returns an AST representation of a relation schema (flash-gordon)
|
19
21
|
* Plugin system supports schema plugins (flash-gordon)
|
data/lib/rom/association_set.rb
CHANGED
@@ -32,6 +32,11 @@ module ROM
|
|
32
32
|
# @return [ROM::SQL::Relation::Name] the target relation
|
33
33
|
option :target, reader: true
|
34
34
|
|
35
|
+
# Create an association object
|
36
|
+
#
|
37
|
+
# @param [Definition] definition The association definition object
|
38
|
+
# @param [RelationRegistry] relations The relation registry
|
39
|
+
#
|
35
40
|
# @api public
|
36
41
|
def self.new(definition, relations)
|
37
42
|
super(
|
@@ -42,62 +47,116 @@ module ROM
|
|
42
47
|
)
|
43
48
|
end
|
44
49
|
|
50
|
+
# Return if an association has an alias
|
51
|
+
#
|
52
|
+
# @return [Boolean]
|
53
|
+
#
|
45
54
|
# @api public
|
46
55
|
def aliased?
|
47
56
|
definition.aliased?
|
48
57
|
end
|
49
58
|
|
59
|
+
# Return association alias
|
60
|
+
#
|
61
|
+
# @return [Symbol]
|
62
|
+
#
|
50
63
|
# @api public
|
51
64
|
def as
|
52
65
|
definition.as
|
53
66
|
end
|
54
67
|
|
68
|
+
# Return association canonical name
|
69
|
+
#
|
70
|
+
# @return [Symbol]
|
71
|
+
#
|
55
72
|
# @api public
|
56
73
|
def name
|
57
74
|
definition.name
|
58
75
|
end
|
59
76
|
|
77
|
+
# Return the name of a custom relation view that should be use to
|
78
|
+
# extend or override default association view
|
79
|
+
#
|
80
|
+
# @return [Symbol]
|
81
|
+
#
|
60
82
|
# @api public
|
61
83
|
def view
|
62
84
|
definition.view
|
63
85
|
end
|
64
86
|
|
87
|
+
# Return association foreign key name
|
88
|
+
#
|
89
|
+
# @return [Symbol]
|
90
|
+
#
|
65
91
|
# @api public
|
66
92
|
def foreign_key
|
67
93
|
definition.foreign_key
|
68
94
|
end
|
69
95
|
|
96
|
+
# Return result type
|
97
|
+
#
|
98
|
+
# This can be either :one or :many
|
99
|
+
#
|
100
|
+
# @return [Symbol]
|
101
|
+
#
|
70
102
|
# @api public
|
71
103
|
def result
|
72
104
|
definition.result
|
73
105
|
end
|
74
106
|
|
107
|
+
# Return if a custom view should override default association view
|
108
|
+
#
|
109
|
+
# @return [Boolean]
|
110
|
+
#
|
75
111
|
# @api public
|
76
112
|
def override?
|
77
113
|
definition.override
|
78
114
|
end
|
79
115
|
|
116
|
+
# Return the name of a key in tuples under which loaded association data are returned
|
117
|
+
#
|
118
|
+
# @return [Symbol]
|
119
|
+
#
|
80
120
|
# @api public
|
81
121
|
def key
|
82
122
|
as || name
|
83
123
|
end
|
84
124
|
|
125
|
+
# Applies custom view to the default association view
|
126
|
+
#
|
127
|
+
# @return [Relation]
|
128
|
+
#
|
85
129
|
# @api protected
|
86
130
|
def apply_view(schema, relation)
|
87
131
|
view_rel = relation.public_send(view)
|
88
132
|
schema.merge(view_rel.schema).uniq(&:key).(view_rel)
|
89
133
|
end
|
90
134
|
|
135
|
+
# Return combine keys hash
|
136
|
+
#
|
137
|
+
# Combine keys are used for merging associated data together, typically these
|
138
|
+
# are the same as fk<=>pk mapping
|
139
|
+
#
|
140
|
+
# @return [Hash<Symbol=>Symbol>]
|
141
|
+
#
|
91
142
|
# @api public
|
92
143
|
def combine_keys
|
93
|
-
{ source_key => target_key }
|
144
|
+
definition.combine_keys || { source_key => target_key }
|
94
145
|
end
|
95
146
|
|
147
|
+
# Return names of source PKs and target FKs
|
148
|
+
#
|
149
|
+
# @return [Array<Symbol>]
|
150
|
+
#
|
96
151
|
# @api private
|
97
152
|
def join_key_map
|
98
153
|
join_keys.to_a.flatten(1).map(&:key)
|
99
154
|
end
|
100
155
|
|
156
|
+
# Return target relation configured as a combine node
|
157
|
+
#
|
158
|
+
# @return [Relation]
|
159
|
+
#
|
101
160
|
# @api private
|
102
161
|
def node
|
103
162
|
target.with(
|
@@ -106,6 +165,10 @@ module ROM
|
|
106
165
|
)
|
107
166
|
end
|
108
167
|
|
168
|
+
# Return target relation as a wrap node
|
169
|
+
#
|
170
|
+
# @return [Relation]
|
171
|
+
#
|
109
172
|
# @api private
|
110
173
|
def wrap
|
111
174
|
target.with(
|
@@ -115,6 +178,10 @@ module ROM
|
|
115
178
|
)
|
116
179
|
end
|
117
180
|
|
181
|
+
# Prepare association's target relation for composition
|
182
|
+
#
|
183
|
+
# @return [Relation]
|
184
|
+
#
|
118
185
|
# @api private
|
119
186
|
def prepare(target)
|
120
187
|
if override?
|
@@ -124,6 +191,10 @@ module ROM
|
|
124
191
|
end
|
125
192
|
end
|
126
193
|
|
194
|
+
# Return if this association's source relation is the same as the target
|
195
|
+
#
|
196
|
+
# @return [Boolean]
|
197
|
+
#
|
127
198
|
# @api private
|
128
199
|
def self_ref?
|
129
200
|
source.name.dataset == target.name.dataset
|
@@ -55,16 +55,20 @@ module ROM
|
|
55
55
|
# @return [TrueClass,FalseClass] Whether custom view should override default one or not
|
56
56
|
option :override, optional: true, default: -> { false }
|
57
57
|
|
58
|
+
# @!attribute [r] combine_keys
|
59
|
+
# @return [Hash<Symbol=>Symbol>] Override inferred combine keys
|
60
|
+
option :combine_keys, optional: true
|
61
|
+
|
58
62
|
# Instantiate a new association definition
|
59
63
|
#
|
60
64
|
# @param [Symbol] source The name of the source dataset
|
61
65
|
# @param [Symbol] target The name of the target dataset
|
62
|
-
# @param [Hash]
|
63
|
-
# @option
|
64
|
-
# @option
|
65
|
-
# @option
|
66
|
-
# @option
|
67
|
-
# @option
|
66
|
+
# @param [Hash] opts The option hash
|
67
|
+
# @option opts [Symbol] :as The name of the association (defaults to target)
|
68
|
+
# @option opts [Symbol] :relation The name of the target relation (defaults to target)
|
69
|
+
# @option opts [Symbol] :foreign_key The name of a custom foreign key
|
70
|
+
# @option opts [Symbol] :view The name of a custom relation view on the target's relation side
|
71
|
+
# @option opts [TrueClass,FalseClass] :override Whether provided :view should override association's default view
|
68
72
|
#
|
69
73
|
# @api public
|
70
74
|
def self.new(source, target, opts = EMPTY_HASH)
|
@@ -96,16 +100,28 @@ module ROM
|
|
96
100
|
options
|
97
101
|
end
|
98
102
|
|
103
|
+
# Return true if association's default relation view should be overridden by a custom one
|
104
|
+
#
|
105
|
+
# @return [Boolean]
|
106
|
+
#
|
99
107
|
# @api public
|
100
108
|
def override?
|
101
109
|
options[:override].equal?(true)
|
102
110
|
end
|
103
111
|
|
112
|
+
# Return true if association is aliased
|
113
|
+
#
|
114
|
+
# @return [Boolean]
|
115
|
+
#
|
104
116
|
# @api public
|
105
117
|
def aliased?
|
106
118
|
options.key?(:as)
|
107
119
|
end
|
108
120
|
|
121
|
+
# Return association class for a given definition object
|
122
|
+
#
|
123
|
+
# @return [Class]
|
124
|
+
#
|
109
125
|
# @api public
|
110
126
|
def type
|
111
127
|
Dry::Core::Inflector.demodulize(self.class.name).to_sym
|
@@ -4,9 +4,12 @@ require 'rom/associations/definitions/abstract'
|
|
4
4
|
module ROM
|
5
5
|
module Associations
|
6
6
|
module Definitions
|
7
|
+
# @api private
|
7
8
|
class ManyToMany < Abstract
|
8
9
|
result :many
|
9
10
|
|
11
|
+
# @!attribute [r] through
|
12
|
+
# @return [ThroughIdentifier] The name of the "through" relation
|
10
13
|
option :through, reader: true
|
11
14
|
|
12
15
|
# @api private
|
@@ -3,7 +3,12 @@ require 'rom/associations/abstract'
|
|
3
3
|
|
4
4
|
module ROM
|
5
5
|
module Associations
|
6
|
+
# Abstract many-to-many association type
|
7
|
+
#
|
8
|
+
# @api public
|
6
9
|
class ManyToMany < Abstract
|
10
|
+
# @!attribute [r] join_relation
|
11
|
+
# @return [Relation] Intermediate join relation
|
7
12
|
attr_reader :join_relation
|
8
13
|
|
9
14
|
# @api private
|
@@ -12,26 +17,49 @@ module ROM
|
|
12
17
|
@join_relation = relations[through]
|
13
18
|
end
|
14
19
|
|
20
|
+
# Adapters should implement this method
|
21
|
+
#
|
22
|
+
# @abstract
|
23
|
+
#
|
15
24
|
# @api public
|
16
25
|
def call(*)
|
17
26
|
raise NotImplementedError
|
18
27
|
end
|
19
28
|
|
29
|
+
# Return configured or inferred FK name
|
30
|
+
#
|
31
|
+
# @return [Symbol]
|
32
|
+
#
|
20
33
|
# @api public
|
21
34
|
def foreign_key
|
22
35
|
definition.foreign_key || join_relation.foreign_key(source.name)
|
23
36
|
end
|
24
37
|
|
38
|
+
# Return join-relation name
|
39
|
+
#
|
40
|
+
# @return [Symbol]
|
41
|
+
#
|
25
42
|
# @api public
|
26
43
|
def through
|
27
44
|
definition.through
|
28
45
|
end
|
29
46
|
|
47
|
+
# Return parent's relation combine keys
|
48
|
+
#
|
49
|
+
# @return [Hash<Symbol=>Symbol>]
|
50
|
+
#
|
30
51
|
# @api private
|
31
52
|
def parent_combine_keys
|
32
53
|
target.associations[source.name].combine_keys.to_a.flatten(1)
|
33
54
|
end
|
34
55
|
|
56
|
+
# Associate child tuples with the provided parent
|
57
|
+
#
|
58
|
+
# @param [Array<Hash>] children An array with child tuples
|
59
|
+
# @param [Array,Hash] parent An array with parent tuples or a single tuple
|
60
|
+
#
|
61
|
+
# @return [Array<Hash>]
|
62
|
+
#
|
35
63
|
# @api private
|
36
64
|
def associate(children, parent)
|
37
65
|
((spk, sfk), (tfk, tpk)) = join_key_map
|
@@ -48,16 +76,28 @@ module ROM
|
|
48
76
|
|
49
77
|
protected
|
50
78
|
|
79
|
+
# Primary key name on the source side
|
80
|
+
#
|
81
|
+
# @return [Symbol]
|
82
|
+
#
|
51
83
|
# @api protected
|
52
84
|
def source_key
|
53
85
|
source.primary_key
|
54
86
|
end
|
55
87
|
|
88
|
+
# Foreign key name on the target side
|
89
|
+
#
|
90
|
+
# @return [Symbol]
|
91
|
+
#
|
56
92
|
# @api protected
|
57
93
|
def target_key
|
58
94
|
foreign_key
|
59
95
|
end
|
60
96
|
|
97
|
+
# Return association for many-to-many-through
|
98
|
+
#
|
99
|
+
# @return [Association]
|
100
|
+
#
|
61
101
|
# @api protected
|
62
102
|
def join_assoc
|
63
103
|
if join_relation.associations.key?(through.assoc_name)
|
@@ -67,6 +107,10 @@ module ROM
|
|
67
107
|
end
|
68
108
|
end
|
69
109
|
|
110
|
+
# Return a [pk, fk] mapping for source/target relations
|
111
|
+
#
|
112
|
+
# @return [Array<Symbol>]
|
113
|
+
#
|
70
114
|
# @api protected
|
71
115
|
def join_key_map
|
72
116
|
left = super
|
@@ -2,17 +2,35 @@ require 'rom/associations/abstract'
|
|
2
2
|
|
3
3
|
module ROM
|
4
4
|
module Associations
|
5
|
+
# Abstract many-to-one association type
|
6
|
+
#
|
7
|
+
# @api public
|
5
8
|
class ManyToOne < Abstract
|
9
|
+
# Adapters must implement this method
|
10
|
+
#
|
11
|
+
# @abstract
|
12
|
+
#
|
6
13
|
# @api public
|
7
14
|
def call(*)
|
8
15
|
raise NotImplementedError
|
9
16
|
end
|
10
17
|
|
18
|
+
# Return configured or inferred FK name
|
19
|
+
#
|
20
|
+
# @return [Symbol]
|
21
|
+
#
|
11
22
|
# @api public
|
12
23
|
def foreign_key
|
13
24
|
definition.foreign_key || source.foreign_key(target.name)
|
14
25
|
end
|
15
26
|
|
27
|
+
# Associate child with a parent
|
28
|
+
#
|
29
|
+
# @param [Hash] child The child tuple
|
30
|
+
# @param [Hash] parent The parent tuple
|
31
|
+
#
|
32
|
+
# @return [Hash]
|
33
|
+
#
|
16
34
|
# @api private
|
17
35
|
def associate(child, parent)
|
18
36
|
fk, pk = join_key_map
|
@@ -21,11 +39,19 @@ module ROM
|
|
21
39
|
|
22
40
|
protected
|
23
41
|
|
42
|
+
# Return foreign key on the source side
|
43
|
+
#
|
44
|
+
# @return [Symbol]
|
45
|
+
#
|
24
46
|
# @api protected
|
25
47
|
def source_key
|
26
48
|
foreign_key
|
27
49
|
end
|
28
50
|
|
51
|
+
# Return primary key on the target side
|
52
|
+
#
|
53
|
+
# @return [Symbol]
|
54
|
+
#
|
29
55
|
# @api protected
|
30
56
|
def target_key
|
31
57
|
target.schema.primary_key_name
|