rom 0.9.1 → 1.0.0.beta1
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/.rubocop_todo.yml +30 -12
- data/.travis.yml +1 -1
- data/CHANGELOG.md +24 -0
- data/Gemfile +7 -3
- data/README.md +24 -11
- data/lib/rom.rb +9 -26
- data/lib/rom/command.rb +113 -75
- data/lib/rom/commands/class_interface.rb +115 -0
- data/lib/rom/commands/graph.rb +17 -23
- data/lib/rom/commands/graph/builder.rb +176 -0
- data/lib/rom/commands/graph/class_interface.rb +8 -2
- data/lib/rom/commands/graph/input_evaluator.rb +13 -9
- data/lib/rom/commands/lazy.rb +23 -17
- data/lib/rom/commands/lazy/create.rb +23 -0
- data/lib/rom/commands/lazy/delete.rb +27 -0
- data/lib/rom/commands/lazy/update.rb +34 -0
- data/lib/rom/commands/result.rb +14 -0
- data/lib/rom/commands/update.rb +0 -4
- data/lib/rom/configuration.rb +86 -0
- data/lib/rom/{setup_dsl/setup.rb → configuration_dsl.rb} +9 -7
- data/lib/rom/configuration_dsl/command.rb +43 -0
- data/lib/rom/{setup_dsl → configuration_dsl}/command_dsl.rb +5 -4
- data/lib/rom/configuration_dsl/mapper.rb +37 -0
- data/lib/rom/{setup_dsl → configuration_dsl}/mapper_dsl.rb +11 -5
- data/lib/rom/configuration_dsl/relation.rb +26 -0
- data/lib/rom/configuration_plugin.rb +17 -0
- data/lib/rom/constants.rb +5 -12
- data/lib/rom/container.rb +11 -8
- data/lib/rom/create_container.rb +61 -0
- data/lib/rom/environment.rb +27 -241
- data/lib/rom/gateway.rb +18 -2
- data/lib/rom/global.rb +24 -0
- data/lib/rom/global/plugin_dsl.rb +2 -0
- data/lib/rom/lint/spec.rb +0 -12
- data/lib/rom/lint/test.rb +0 -31
- data/lib/rom/memory/commands.rb +2 -2
- data/lib/rom/memory/gateway.rb +2 -0
- data/lib/rom/pipeline.rb +1 -1
- data/lib/rom/plugin_base.rb +1 -1
- data/lib/rom/plugin_registry.rb +12 -10
- data/lib/rom/plugins/configuration/configuration_dsl.rb +16 -0
- data/lib/rom/plugins/relation/key_inference.rb +31 -0
- data/lib/rom/plugins/relation/view.rb +90 -0
- data/lib/rom/plugins/relation/view/dsl.rb +32 -0
- data/lib/rom/relation.rb +1 -11
- data/lib/rom/relation/class_interface.rb +37 -50
- data/lib/rom/setup.rb +13 -104
- data/lib/rom/setup/auto_registration.rb +55 -0
- data/lib/rom/setup/finalize.rb +113 -127
- data/lib/rom/setup/finalize/commands.rb +67 -0
- data/lib/rom/setup/finalize/mappers.rb +36 -0
- data/lib/rom/setup/finalize/relations.rb +53 -0
- data/lib/rom/support/configurable.rb +21 -7
- data/lib/rom/version.rb +1 -1
- data/rakelib/mutant.rake +4 -1
- data/rom.gemspec +3 -4
- data/spec/fixtures/app/commands/create_user.rb +2 -0
- data/spec/fixtures/app/mappers/user_list.rb +2 -0
- data/spec/fixtures/app/relations/users.rb +2 -0
- data/spec/fixtures/lib/persistence/commands/create_user.rb +6 -0
- data/spec/fixtures/lib/persistence/mappers/user_list.rb +6 -0
- data/spec/fixtures/lib/persistence/relations/users.rb +6 -0
- data/spec/{unit/rom → integration}/command_registry_spec.rb +8 -9
- data/spec/integration/commands/create_spec.rb +17 -13
- data/spec/integration/commands/delete_spec.rb +12 -11
- data/spec/integration/commands/error_handling_spec.rb +5 -4
- data/spec/integration/commands/graph_builder_spec.rb +213 -0
- data/spec/integration/commands/graph_spec.rb +112 -49
- data/spec/integration/commands/update_spec.rb +14 -11
- data/spec/integration/commands_spec.rb +60 -0
- data/spec/integration/mappers/combine_spec.rb +7 -6
- data/spec/integration/mappers/deep_embedded_spec.rb +5 -6
- data/spec/integration/mappers/definition_dsl_spec.rb +19 -18
- data/spec/integration/mappers/embedded_spec.rb +11 -12
- data/spec/integration/mappers/exclude_spec.rb +5 -6
- data/spec/integration/mappers/fold_spec.rb +8 -7
- data/spec/integration/mappers/group_spec.rb +16 -15
- data/spec/integration/mappers/overwrite_attributes_value_spec.rb +5 -5
- data/spec/integration/mappers/prefix_separator_spec.rb +5 -7
- data/spec/integration/mappers/prefix_spec.rb +5 -7
- data/spec/integration/mappers/prefixing_attributes_spec.rb +7 -7
- data/spec/integration/mappers/registering_custom_mappers_spec.rb +4 -5
- data/spec/integration/mappers/renaming_attributes_spec.rb +18 -18
- data/spec/integration/mappers/step_spec.rb +11 -12
- data/spec/integration/mappers/symbolizing_attributes_spec.rb +11 -8
- data/spec/integration/mappers/unfold_spec.rb +9 -10
- data/spec/integration/mappers/ungroup_spec.rb +10 -11
- data/spec/integration/mappers/unwrap_spec.rb +10 -15
- data/spec/integration/mappers/wrap_spec.rb +16 -15
- data/spec/{unit/rom → integration}/memory/commands/create_spec.rb +7 -5
- data/spec/{unit/rom → integration}/memory/commands/delete_spec.rb +7 -5
- data/spec/{unit/rom → integration}/memory/commands/update_spec.rb +7 -5
- data/spec/integration/multi_env_spec.rb +16 -124
- data/spec/integration/multi_repo_spec.rb +9 -9
- data/spec/integration/relations/default_dataset_spec.rb +15 -0
- data/spec/integration/relations/inheritance_spec.rb +5 -7
- data/spec/integration/relations/reading_spec.rb +32 -65
- data/spec/integration/relations/registry_dsl_spec.rb +5 -4
- data/spec/integration/repositories/extending_relations_spec.rb +6 -7
- data/spec/integration/repositories/setting_logger_spec.rb +5 -7
- data/spec/integration/setup_spec.rb +49 -61
- data/spec/shared/command_graph.rb +50 -0
- data/spec/shared/container.rb +9 -0
- data/spec/shared/gateway_only.rb +6 -0
- data/spec/shared/no_container.rb +16 -0
- data/spec/shared/one_behavior.rb +4 -4
- data/spec/shared/users_and_tasks.rb +5 -17
- data/spec/spec_helper.rb +5 -3
- data/spec/test/memory_repository_lint_test.rb +1 -1
- data/spec/unit/rom/auto_registration_spec.rb +54 -0
- data/spec/unit/rom/commands/graph_spec.rb +18 -44
- data/spec/unit/rom/commands/lazy_spec.rb +246 -35
- data/spec/unit/rom/commands/result_spec.rb +56 -0
- data/spec/unit/rom/commands_spec.rb +9 -73
- data/spec/unit/rom/configurable_spec.rb +49 -0
- data/spec/unit/rom/configuration_spec.rb +61 -0
- data/spec/unit/rom/container_spec.rb +39 -33
- data/spec/unit/rom/create_container_spec.rb +151 -0
- data/spec/unit/rom/environment_spec.rb +123 -0
- data/spec/unit/rom/gateway_spec.rb +58 -2
- data/spec/unit/rom/global_spec.rb +10 -7
- data/spec/unit/rom/plugin_spec.rb +44 -25
- data/spec/unit/rom/plugins/relation/key_inference_spec.rb +27 -0
- data/spec/unit/rom/plugins/relation/view_spec.rb +47 -0
- data/spec/unit/rom/relation/composite_spec.rb +20 -20
- data/spec/unit/rom/relation/curried_spec.rb +10 -11
- data/spec/unit/rom/relation/graph_spec.rb +27 -27
- data/spec/unit/rom/relation/lazy/combine_spec.rb +26 -20
- data/spec/unit/rom/relation/lazy_spec.rb +38 -38
- data/spec/unit/rom/relation/loaded_spec.rb +2 -3
- data/spec/unit/rom/relation_spec.rb +39 -2
- metadata +58 -66
- data/lib/rom/commands/abstract.rb +0 -184
- data/lib/rom/environment_plugin.rb +0 -17
- data/lib/rom/environment_plugins/auto_registration.rb +0 -38
- data/lib/rom/repository.rb +0 -16
- data/lib/rom/setup_dsl/command.rb +0 -36
- data/lib/rom/setup_dsl/mapper.rb +0 -32
- data/lib/rom/setup_dsl/relation.rb +0 -30
- data/spec/integration/inline_setup_spec.rb +0 -65
- data/spec/unit/rom/repository_spec.rb +0 -12
- data/spec/unit/rom/setup_spec.rb +0 -253
@@ -16,9 +16,13 @@ module ROM
|
|
16
16
|
super
|
17
17
|
|
18
18
|
klass.extend ClassMacros
|
19
|
-
klass.extend Deprecations
|
20
19
|
klass.defines :adapter
|
21
20
|
|
21
|
+
if respond_to?(:adapter) && adapter.nil?
|
22
|
+
raise MissingAdapterIdentifierError,
|
23
|
+
"relation class +#{self}+ is missing the adapter identifier"
|
24
|
+
end
|
25
|
+
|
22
26
|
# Extend with functionality required by adapters *only* if this is a direct
|
23
27
|
# descendant of an adapter-specific relation subclass
|
24
28
|
return unless respond_to?(:adapter) && klass.superclass == ROM::Relation[adapter]
|
@@ -26,10 +30,7 @@ module ROM
|
|
26
30
|
klass.class_eval do
|
27
31
|
use :registry_reader
|
28
32
|
|
29
|
-
defines :gateway, :dataset, :register_as
|
30
|
-
|
31
|
-
deprecate_class_method :repository, :gateway
|
32
|
-
deprecate :repository, :gateway
|
33
|
+
defines :gateway, :dataset, :dataset_proc, :register_as
|
33
34
|
|
34
35
|
gateway :default
|
35
36
|
|
@@ -44,6 +45,29 @@ module ROM
|
|
44
45
|
# @api public
|
45
46
|
attr_reader :name
|
46
47
|
|
48
|
+
# Set dataset name
|
49
|
+
#
|
50
|
+
# If a block is passed it will be evaluated in the context of the dataset
|
51
|
+
# to define the default dataset which will be injected into a relation
|
52
|
+
# when setting up relation registry
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# class Relations::Users < ROM::Relation[:memory]
|
56
|
+
# dataset :users
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# class Users < ROM::Relation[:memory]
|
60
|
+
# dataset { sort_by(:id) }
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# @param [Symbol] value The name of the dataset
|
64
|
+
#
|
65
|
+
# @api public
|
66
|
+
def self.dataset(value = Undefined, &block)
|
67
|
+
dataset_proc(block) if block
|
68
|
+
super
|
69
|
+
end
|
70
|
+
|
47
71
|
# Set or get name under which a relation will be registered
|
48
72
|
#
|
49
73
|
# This defaults to `dataset` or `default_name` for descendant relations
|
@@ -65,12 +89,6 @@ module ROM
|
|
65
89
|
end
|
66
90
|
end
|
67
91
|
|
68
|
-
# @api public
|
69
|
-
def self.exposed_relations(*args)
|
70
|
-
Deprecations.announce("#{self}.exposed_relations", 'this method has no effect anymore')
|
71
|
-
Set.new
|
72
|
-
end
|
73
|
-
|
74
92
|
# @api private
|
75
93
|
def initialize(dataset, options = EMPTY_HASH)
|
76
94
|
@name = self.class.dataset
|
@@ -142,51 +160,20 @@ module ROM
|
|
142
160
|
# @api private
|
143
161
|
def default_name
|
144
162
|
return unless name
|
145
|
-
Inflector.underscore(name).
|
163
|
+
Inflector.underscore(name).tr('/', '_').to_sym
|
146
164
|
end
|
147
165
|
|
148
|
-
# Build relation registry of specified descendant classes
|
149
|
-
#
|
150
|
-
# This is used by the setup
|
151
|
-
#
|
152
|
-
# @param [Hash] gateways
|
153
|
-
# @param [Array] descendants a list of relation descendants
|
154
|
-
#
|
155
|
-
# @return [Hash]
|
156
|
-
#
|
157
166
|
# @api private
|
158
|
-
def
|
159
|
-
|
160
|
-
|
161
|
-
descendants.each do |klass|
|
162
|
-
# TODO: raise a meaningful error here and add spec covering the case
|
163
|
-
# where klass' gateway points to non-existant repo
|
164
|
-
gateway = gateways.fetch(klass.gateway)
|
165
|
-
dataset = gateway.dataset(klass.dataset)
|
166
|
-
|
167
|
-
relation = klass.new(dataset, __registry__: registry)
|
168
|
-
|
169
|
-
name = klass.register_as
|
170
|
-
|
171
|
-
if registry.key?(name)
|
172
|
-
raise RelationAlreadyDefinedError,
|
173
|
-
"Relation with `register_as #{name.inspect}` registered more " \
|
174
|
-
"than once"
|
175
|
-
end
|
176
|
-
|
177
|
-
registry[name] = relation
|
178
|
-
end
|
179
|
-
|
180
|
-
registry.each_value do |relation|
|
181
|
-
relation.class.finalize(registry, relation)
|
182
|
-
end
|
183
|
-
|
184
|
-
registry
|
167
|
+
def curried
|
168
|
+
Curried
|
185
169
|
end
|
186
170
|
|
187
171
|
# @api private
|
188
|
-
def
|
189
|
-
|
172
|
+
def view_methods
|
173
|
+
ancestor_methods = ancestors.reject { |klass| klass == self }
|
174
|
+
.map(&:instance_methods).flatten
|
175
|
+
|
176
|
+
instance_methods - ancestor_methods
|
190
177
|
end
|
191
178
|
|
192
179
|
# Hook to finalize a relation after its instance was created
|
data/lib/rom/setup.rb
CHANGED
@@ -1,38 +1,7 @@
|
|
1
|
-
require 'rom/
|
2
|
-
|
3
|
-
require 'rom/setup/finalize'
|
4
|
-
require 'rom/support/deprecations'
|
1
|
+
require 'rom/setup/auto_registration'
|
5
2
|
|
6
3
|
module ROM
|
7
|
-
# Exposes DSL for defining relations, mappers and commands
|
8
|
-
#
|
9
|
-
# @api public
|
10
4
|
class Setup
|
11
|
-
include Configurable
|
12
|
-
|
13
|
-
extend Deprecations
|
14
|
-
include Equalizer.new(:gateways, :container)
|
15
|
-
|
16
|
-
# @return [Hash] configured gateways
|
17
|
-
#
|
18
|
-
# @api private
|
19
|
-
attr_reader :gateways
|
20
|
-
|
21
|
-
# @attr_reader [Hash<Gateway=>Symbol>] gateway_map Environment gateway map
|
22
|
-
#
|
23
|
-
# @api private
|
24
|
-
attr_reader :gateway_map
|
25
|
-
|
26
|
-
# Deprecated accessor for gateways.
|
27
|
-
#
|
28
|
-
# @see gateways
|
29
|
-
deprecate :repositories, :gateways
|
30
|
-
|
31
|
-
# @return [Symbol] default (first) adapter
|
32
|
-
#
|
33
|
-
# @api private
|
34
|
-
attr_reader :default_adapter
|
35
|
-
|
36
5
|
# @return [Array] registered relation subclasses
|
37
6
|
#
|
38
7
|
# @api private
|
@@ -48,99 +17,39 @@ module ROM
|
|
48
17
|
# @api private
|
49
18
|
attr_reader :command_classes
|
50
19
|
|
51
|
-
# @return [Conainer] finalized container after setup phase is over
|
52
|
-
#
|
53
|
-
# @api private
|
54
|
-
attr_reader :container
|
55
|
-
alias_method :env, :container
|
56
|
-
|
57
20
|
# @api private
|
58
|
-
def initialize
|
59
|
-
@gateways = gateways
|
60
|
-
|
61
|
-
@gateway_map = options.fetch(:gateway_map, {})
|
62
|
-
@default_adapter = options.fetch(:default_adapter, nil)
|
63
|
-
|
21
|
+
def initialize
|
64
22
|
@relation_classes = []
|
65
23
|
@command_classes = []
|
66
24
|
@mapper_classes = []
|
67
|
-
@container = nil
|
68
|
-
end
|
69
|
-
|
70
|
-
# Finalize the setup
|
71
|
-
#
|
72
|
-
# @return [Container] frozen container with access to gateways,
|
73
|
-
# relations, mappers and commands
|
74
|
-
#
|
75
|
-
# @api public
|
76
|
-
def finalize
|
77
|
-
raise EnvAlreadyFinalizedError if container
|
78
|
-
|
79
|
-
# initialize default configs for all gateways
|
80
|
-
gateways.each_key do |key|
|
81
|
-
gateway_config = config.gateways[key]
|
82
|
-
|
83
|
-
gateway_config.infer_relations = true unless gateway_config.key?(:infer_relations)
|
84
|
-
end
|
85
|
-
|
86
|
-
finalize = Finalize.new(
|
87
|
-
gateways: gateways,
|
88
|
-
gateway_map: gateway_map,
|
89
|
-
relation_classes: relation_classes,
|
90
|
-
command_classes: command_classes,
|
91
|
-
mappers: mapper_classes,
|
92
|
-
config: config.freeze
|
93
|
-
)
|
94
|
-
|
95
|
-
@container = finalize.run!
|
96
|
-
end
|
97
|
-
|
98
|
-
# Return gateway identified by name
|
99
|
-
#
|
100
|
-
# @return [Gateway]
|
101
|
-
#
|
102
|
-
# @api private
|
103
|
-
def [](name)
|
104
|
-
gateways.fetch(name)
|
105
25
|
end
|
106
26
|
|
107
27
|
# Relation sub-classes are being registered with this method during setup
|
108
28
|
#
|
109
29
|
# @api private
|
110
|
-
def register_relation(
|
111
|
-
@relation_classes
|
30
|
+
def register_relation(*klasses)
|
31
|
+
klasses.reduce(@relation_classes, :<<)
|
112
32
|
end
|
113
33
|
|
114
34
|
# Mapper sub-classes are being registered with this method during setup
|
115
35
|
#
|
116
36
|
# @api private
|
117
|
-
def register_mapper(
|
118
|
-
@mapper_classes
|
37
|
+
def register_mapper(*klasses)
|
38
|
+
klasses.reduce(@mapper_classes, :<<)
|
119
39
|
end
|
120
40
|
|
121
41
|
# Command sub-classes are being registered with this method during setup
|
122
42
|
#
|
123
43
|
# @api private
|
124
|
-
def register_command(
|
125
|
-
@command_classes
|
126
|
-
end
|
127
|
-
|
128
|
-
# Hook for respond_to? used internally
|
129
|
-
#
|
130
|
-
# @api private
|
131
|
-
def respond_to_missing?(name, _include_context = false)
|
132
|
-
gateways.key?(name)
|
44
|
+
def register_command(*klasses)
|
45
|
+
klasses.reduce(@command_classes, :<<)
|
133
46
|
end
|
134
47
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
#
|
141
|
-
# @api private
|
142
|
-
def method_missing(name, *)
|
143
|
-
gateways.fetch(name) { super }
|
48
|
+
def auto_registration(directory, options = {})
|
49
|
+
auto_registration = AutoRegistration.new(directory, options)
|
50
|
+
auto_registration.relations.map { |r| register_relation(r) }
|
51
|
+
auto_registration.commands.map { |r| register_command(r) }
|
52
|
+
auto_registration.mappers.map { |r| register_mapper(r) }
|
144
53
|
end
|
145
54
|
end
|
146
55
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
require 'rom/support/constants'
|
4
|
+
require 'rom/support/inflector'
|
5
|
+
require 'rom/support/options'
|
6
|
+
|
7
|
+
module ROM
|
8
|
+
class AutoRegistration
|
9
|
+
include Options
|
10
|
+
|
11
|
+
option :namespace, reader: true, type: [TrueClass, FalseClass], default: true
|
12
|
+
|
13
|
+
attr_reader :globs, :directory
|
14
|
+
|
15
|
+
def initialize(directory, options = EMPTY_HASH)
|
16
|
+
super
|
17
|
+
@directory = directory
|
18
|
+
@globs = Hash[[:relations, :commands, :mappers].map { |name|
|
19
|
+
[name, Pathname(directory).join("#{name}/**/*.rb")]
|
20
|
+
}]
|
21
|
+
end
|
22
|
+
|
23
|
+
def relations
|
24
|
+
load_entities(:relations)
|
25
|
+
end
|
26
|
+
|
27
|
+
def commands
|
28
|
+
load_entities(:commands)
|
29
|
+
end
|
30
|
+
|
31
|
+
def mappers
|
32
|
+
load_entities(:mappers)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def load_entities(entity)
|
38
|
+
Dir[globs[entity]].map do |file|
|
39
|
+
require file
|
40
|
+
Inflector.constantize(const_name(entity, file))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def const_name(entity, file)
|
45
|
+
name =
|
46
|
+
if namespace
|
47
|
+
file.gsub("#{directory.dirname}/", '')
|
48
|
+
else
|
49
|
+
file.gsub("#{directory}/#{entity}/", '')
|
50
|
+
end.gsub('.rb', '')
|
51
|
+
|
52
|
+
Inflector.camelize(name)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/rom/setup/finalize.rb
CHANGED
@@ -2,159 +2,145 @@ require 'rom/relation'
|
|
2
2
|
require 'rom/command'
|
3
3
|
|
4
4
|
require 'rom/support/registry'
|
5
|
-
require 'rom/relation_registry'
|
6
5
|
require 'rom/command_registry'
|
7
6
|
require 'rom/mapper_registry'
|
8
7
|
|
9
8
|
require 'rom/container'
|
9
|
+
require 'rom/setup/finalize/commands'
|
10
|
+
require 'rom/setup/finalize/relations'
|
11
|
+
require 'rom/setup/finalize/mappers'
|
12
|
+
|
13
|
+
# temporary
|
14
|
+
require 'rom/configuration_dsl/relation'
|
10
15
|
|
11
16
|
module ROM
|
12
|
-
|
13
|
-
|
17
|
+
# This giant builds an container using defined classes for core parts of ROM
|
18
|
+
#
|
19
|
+
# It is used by the setup object after it's done gathering class definitions
|
20
|
+
#
|
21
|
+
# @private
|
22
|
+
class Finalize
|
23
|
+
attr_reader :gateways, :repo_adapter, :datasets, :gateway_map,
|
24
|
+
:relation_classes, :mapper_classes, :mapper_objects, :command_classes, :config
|
25
|
+
|
26
|
+
# @api private
|
27
|
+
def initialize(options)
|
28
|
+
@gateways = options.fetch(:gateways)
|
29
|
+
@gateway_map = options.fetch(:gateway_map)
|
30
|
+
|
31
|
+
@relation_classes = options.fetch(:relation_classes)
|
32
|
+
@command_classes = options.fetch(:command_classes)
|
33
|
+
|
34
|
+
mappers = options.fetch(:mappers, [])
|
35
|
+
@mapper_classes = mappers.select { |mapper| mapper.is_a?(Class) }
|
36
|
+
@mapper_objects = (mappers - @mapper_classes).reduce(:merge) || {}
|
37
|
+
|
38
|
+
@config = options.fetch(:config)
|
39
|
+
|
40
|
+
initialize_datasets
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return adapter identifier for a given gateway object
|
14
44
|
#
|
15
|
-
#
|
45
|
+
# @return [Symbol]
|
16
46
|
#
|
17
|
-
# @private
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# @api private
|
23
|
-
def initialize(options)
|
24
|
-
@gateways = options.fetch(:gateways)
|
25
|
-
@gateway_map = options.fetch(:gateway_map)
|
26
|
-
|
27
|
-
@relation_classes = options.fetch(:relation_classes)
|
28
|
-
@command_classes = options.fetch(:command_classes)
|
29
|
-
|
30
|
-
mappers = options.fetch(:mappers, [])
|
31
|
-
@mapper_classes = mappers.select { |mapper| mapper.is_a?(Class) }
|
32
|
-
@mapper_objects = (mappers - @mapper_classes).reduce(:merge) || {}
|
47
|
+
# @api private
|
48
|
+
def adapter_for(gateway)
|
49
|
+
@gateway_map.fetch(gateways[gateway])
|
50
|
+
end
|
33
51
|
|
34
|
-
|
52
|
+
# Run the finalization process
|
53
|
+
#
|
54
|
+
# This creates relations, mappers and commands
|
55
|
+
#
|
56
|
+
# @return [Container]
|
57
|
+
#
|
58
|
+
# @api private
|
59
|
+
def run!
|
60
|
+
infer_relations_relations
|
35
61
|
|
36
|
-
|
37
|
-
|
62
|
+
relations = load_relations
|
63
|
+
mappers = load_mappers
|
64
|
+
commands = load_commands(relations)
|
38
65
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
# @api private
|
44
|
-
def adapter_for(gateway)
|
45
|
-
@gateway_map.fetch(gateways[gateway])
|
46
|
-
end
|
66
|
+
container = Container.new(gateways, relations, mappers, commands)
|
67
|
+
container.freeze
|
68
|
+
container
|
69
|
+
end
|
47
70
|
|
48
|
-
|
49
|
-
#
|
50
|
-
# This creates relations, mappers and commands
|
51
|
-
#
|
52
|
-
# @return [Container]
|
53
|
-
#
|
54
|
-
# @api private
|
55
|
-
def run!
|
56
|
-
infer_relations_relations
|
57
|
-
|
58
|
-
relations = load_relations
|
59
|
-
mappers = load_mappers
|
60
|
-
commands = load_commands(relations)
|
61
|
-
|
62
|
-
Container.new(gateways, relations, mappers, commands)
|
63
|
-
end
|
71
|
+
private
|
64
72
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
h[key] = gateway.schema if config.gateways[key][:infer_relations]
|
77
|
-
end
|
73
|
+
# Infer all datasets using configured gateways
|
74
|
+
#
|
75
|
+
# Not all gateways can do that, by default an empty array is returned
|
76
|
+
#
|
77
|
+
# @return [Hash] gateway name => array with datasets map
|
78
|
+
#
|
79
|
+
# @api private
|
80
|
+
def initialize_datasets
|
81
|
+
@datasets = gateways.each_with_object({}) do |(key, gateway), h|
|
82
|
+
infer_relations = config.gateways && config.gateways[key] && config.gateways[key][:infer_relations]
|
83
|
+
h[key] = gateway.schema if infer_relations
|
78
84
|
end
|
85
|
+
end
|
79
86
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
87
|
+
# Build entire relation registry from all known relation subclasses
|
88
|
+
#
|
89
|
+
# This includes both classes created via DSL and explicit definitions
|
90
|
+
#
|
91
|
+
# @api private
|
92
|
+
def load_relations
|
93
|
+
FinalizeRelations.new(gateways, relation_classes).run!
|
94
|
+
end
|
89
95
|
|
90
|
-
|
91
|
-
|
92
|
-
|
96
|
+
# @api private
|
97
|
+
def load_mappers
|
98
|
+
FinalizeMappers.new(mapper_classes, mapper_objects).run!
|
99
|
+
end
|
93
100
|
|
94
|
-
|
95
|
-
|
96
|
-
|
101
|
+
# Build entire command registries
|
102
|
+
#
|
103
|
+
# This includes both classes created via DSL and explicit definitions
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
def load_commands(relations)
|
107
|
+
FinalizeCommands.new(relations, gateways, command_classes).run!
|
108
|
+
end
|
97
109
|
|
98
|
-
|
99
|
-
|
100
|
-
|
110
|
+
# For every dataset infered from gateways we infer a relation
|
111
|
+
#
|
112
|
+
# Relations explicitly defined are being skipped
|
113
|
+
#
|
114
|
+
# @api private
|
115
|
+
def infer_relations_relations
|
116
|
+
datasets.each do |gateway, schema|
|
117
|
+
schema.each do |name|
|
118
|
+
if infer_relation?(gateway, name)
|
119
|
+
klass = ROM::ConfigurationDSL::Relation.build_class(name, adapter: adapter_for(gateway))
|
120
|
+
klass.gateway(gateway)
|
121
|
+
klass.dataset(name)
|
122
|
+
@relation_classes << klass
|
101
123
|
else
|
102
|
-
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
Registry.new(registry_hash)
|
107
|
-
end
|
108
|
-
|
109
|
-
# Build entire command registries
|
110
|
-
#
|
111
|
-
# This includes both classes created via DSL and explicit definitions
|
112
|
-
#
|
113
|
-
# @api private
|
114
|
-
def load_commands(relations)
|
115
|
-
registry = Command.registry(relations, gateways, command_classes)
|
116
|
-
|
117
|
-
commands = registry.each_with_object({}) do |(name, rel_commands), h|
|
118
|
-
h[name] = CommandRegistry.new(rel_commands)
|
119
|
-
end
|
120
|
-
|
121
|
-
Registry.new(commands)
|
122
|
-
end
|
123
|
-
|
124
|
-
# For every dataset infered from gateways we infer a relation
|
125
|
-
#
|
126
|
-
# Relations explicitly defined are being skipped
|
127
|
-
#
|
128
|
-
# @api private
|
129
|
-
def infer_relations_relations
|
130
|
-
datasets.each do |gateway, schema|
|
131
|
-
schema.each do |name|
|
132
|
-
if infer_relation?(gateway, name)
|
133
|
-
klass = Relation.build_class(name, adapter: adapter_for(gateway))
|
134
|
-
klass.gateway(gateway)
|
135
|
-
klass.dataset(name)
|
136
|
-
else
|
137
|
-
next
|
138
|
-
end
|
124
|
+
next
|
139
125
|
end
|
140
126
|
end
|
141
127
|
end
|
128
|
+
end
|
142
129
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
130
|
+
def infer_relation?(gateway, name)
|
131
|
+
inferrable_relations(gateway).include?(name) && relation_classes.none? { |klass|
|
132
|
+
klass.dataset == name
|
133
|
+
}
|
134
|
+
end
|
148
135
|
|
149
|
-
|
150
|
-
|
151
|
-
|
136
|
+
def inferrable_relations(gateway)
|
137
|
+
gateway_config = config.gateways[gateway]
|
138
|
+
schema = gateways[gateway].schema
|
152
139
|
|
153
|
-
|
154
|
-
|
140
|
+
allowed = gateway_config[:inferrable_relations] || schema
|
141
|
+
skipped = gateway_config[:not_inferrable_relations] || []
|
155
142
|
|
156
|
-
|
157
|
-
end
|
143
|
+
schema & allowed - skipped
|
158
144
|
end
|
159
145
|
end
|
160
146
|
end
|