Skip to content

Commit dfa7dc6

Browse files
committed
Improve and simplify gateway config and setup
This makes gateway setup more inline with how components are handled. It'll make it easier to extend configuration with support for global defaults and simplify handling of gateways at runtime, because they now have a name under which they are registered + all config and opts associated with a gateway instance are stored within the gateway registry which makes it easily accessible. It didn't make sense to improve Gateway abstract class because making it backward compatible would be too much work and breaking API would be even more work, considering all the adapters that would have to be updated. In summary: - Simplify gateway handling - Simplify configuring gateways - Add Gateway#name - Move config stuff from gateways environment to Configuration - Stop memoizing plugins in components - Turn Environment into a standard registry with gateways - Move Configuration#relation_classes to rom/compat - Move Configuration#adapter_for_gateway to rom/compat
1 parent d8587d0 commit dfa7dc6

File tree

16 files changed

+335
-203
lines changed

16 files changed

+335
-203
lines changed

lib/rom/compat.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,32 @@
55
module ROM
66
class Configuration
77
def_delegators :@setup, :auto_registration
8+
def_delegators :@gateways, :gateways_map
9+
10+
alias_method :environment, :gateways
11+
12+
# @api private
13+
def relation_classes(gateway = nil)
14+
classes = setup.components.relations.map(&:constant)
15+
16+
return classes unless gateway
17+
18+
gw_name = gateway.is_a?(Symbol) ? gateway : gateways_map[gateway]
19+
classes.select { |rel| rel.gateway == gw_name }
20+
end
21+
22+
# @api private
23+
# @deprecated
24+
def gateways_map
25+
@gateways_map ||= gateways.to_a.map(&:reverse).to_h
26+
end
27+
28+
# @api private
29+
# @deprecated
30+
def adapter_for_gateway(gateway)
31+
ROM.adapters.select do |_key, value|
32+
value.const_defined?(:Gateway) && gateway.is_a?(value.const_get(:Gateway))
33+
end.keys.first
34+
end
835
end
936
end

lib/rom/components/core.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ def apply_plugins
8080
end
8181

8282
# @api public
83-
memoize def plugins
83+
def plugins
8484
configuration.plugins.select { |plugin| plugin.type == self.class.id }
8585
end
8686

8787
# @api public
88-
memoize def plugin_options
88+
def plugin_options
8989
plugins.map(&:config).map(&:to_hash).reduce(:merge) || EMPTY_HASH
9090
end
9191

lib/rom/configuration.rb

Lines changed: 80 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
require "forwardable"
44

55
require "rom/support/notifications"
6-
require "rom/environment"
76
require "rom/setup"
87
require "rom/configuration_dsl"
8+
require "rom/support/configurable"
99
require "rom/support/inflector"
10+
require "rom/gateway_registry"
1011
require "rom/relation_registry"
1112

1213
module ROM
@@ -23,12 +24,13 @@ class Configuration
2324
register_event("configuration.commands.class.before_build")
2425

2526
include ROM::ConfigurationDSL
27+
include Configurable
2628

2729
NoDefaultAdapterError = Class.new(StandardError)
2830

29-
# @!attribute [r] environment
30-
# @return [Environment] Environment object with gateways
31-
attr_reader :environment
31+
# @!attribute [r] gateways
32+
# @return [GatewayRegistry] Configured runtime gateways
33+
attr_reader :gateways
3234

3335
# @!attribute [r] setup
3436
# @return [Setup] Setup object which collects component classes and plugins
@@ -50,24 +52,49 @@ class Configuration
5052
:register_mapper, :register_plugin, :auto_register,
5153
:inflector, :inflector=, :components, :plugins
5254

53-
def_delegators :@environment, :gateways, :gateways_map, :configure, :config
54-
5555
# Initialize a new configuration
5656
#
57-
# @see Environment#initialize
58-
#
5957
# @return [Configuration]
6058
#
6159
# @api private
6260
def initialize(*args, &block)
63-
@environment = Environment.new(*args)
64-
@setup = Setup.new
6561
@notifications = Notifications.event_bus(:configuration)
62+
63+
@setup = Setup.new
6664
@cache = Cache.new
6765

66+
config.gateways = Config.new
67+
@gateways = GatewayRegistry.new({}, cache: cache, config: config.gateways)
68+
69+
configure(*args, &block)
70+
6871
@relations = RelationRegistry.build
72+
end
73+
74+
# @api public
75+
def configure(*args)
76+
unless args.empty?
77+
gateways_config = args.first.is_a?(Hash) ? args.first : {default: args}
78+
79+
gateways_config.each do |name, value|
80+
args = Array(value)
81+
82+
adapter, *rest = args
83+
84+
if rest.size > 1 && rest.last.is_a?(Hash)
85+
load_config(config.gateways[name], {adapter: adapter, args: rest[0..-1], **rest.last})
86+
else
87+
options = rest.first.is_a?(Hash) ? rest.first : {args: rest.flatten(1)}
88+
load_config(config.gateways[name], {adapter: adapter, **options})
89+
end
90+
end
91+
end
92+
93+
load_gateways
94+
95+
yield(self) if block_given?
6996

70-
block&.call(self)
97+
self
7198
end
7299

73100
# @api private
@@ -76,17 +103,6 @@ def finalize
76103
self
77104
end
78105

79-
# @api private
80-
def command_compiler
81-
@command_compiler ||= CommandCompiler.new(
82-
gateways,
83-
relations,
84-
Registry.new,
85-
notifications,
86-
inflector: inflector
87-
)
88-
end
89-
90106
# Apply a plugin to the configuration
91107
#
92108
# @param [Mixed] plugin The plugin identifier, usually a Symbol
@@ -96,10 +112,9 @@ def command_compiler
96112
#
97113
# @api public
98114
def use(plugin, options = {})
99-
if plugin.is_a?(Array)
100-
plugin.each { |p| use(p) }
101-
elsif plugin.is_a?(Hash)
102-
plugin.to_a.each { |p| use(*p) }
115+
case plugin
116+
when Array then plugin.each { |p| use(p) }
117+
when Hash then plugin.to_a.each { |p| use(*p) }
103118
else
104119
ROM.plugin_registry[:configuration].fetch(plugin).apply_to(self, options)
105120
end
@@ -116,42 +131,62 @@ def [](name)
116131
gateways.fetch(name)
117132
end
118133

119-
# Hook for respond_to? used internally
120-
#
121134
# @api private
122-
def respond_to?(name, include_all = false)
123-
gateways.key?(name) || super
135+
def default_gateway
136+
@default_gateway ||= gateways[:default] if gateways.key?(:default)
124137
end
125138

126139
# @api private
127-
def default_gateway
128-
@default_gateway ||= gateways[:default]
140+
def default_adapter
141+
@default_adapter ||= adapter_for_gateway(default_gateway) || ROM.adapters.keys.first
129142
end
130143

131144
# @api private
132-
def adapter_for_gateway(gateway)
133-
ROM.adapters.select do |_key, value|
134-
value.const_defined?(:Gateway) && gateway.is_a?(value.const_get(:Gateway))
135-
end.keys.first
145+
def command_compiler
146+
@command_compiler ||= CommandCompiler.new(
147+
gateways,
148+
relations,
149+
Registry.new,
150+
notifications,
151+
inflector: inflector
152+
)
136153
end
137154

138155
# @api private
139-
def relation_classes(gateway = nil)
140-
classes = setup.components.relations.map(&:constant)
156+
def respond_to_missing?(name, include_all = false)
157+
gateways.key?(name) || super
158+
end
141159

142-
return classes unless gateway
160+
private
143161

144-
gw_name = gateway.is_a?(Symbol) ? gateway : gateways_map[gateway]
145-
classes.select { |rel| rel.gateway == gw_name }
162+
# @api private
163+
def load_gateways
164+
config.gateways.each do |name, gateway_config|
165+
gateway =
166+
if gateway_config.adapter.is_a?(Gateway)
167+
gateway_config.adapter
168+
else
169+
Gateway.setup(gateway_config.adapter, gateway_config)
170+
end
171+
172+
# TODO: this is here to keep backward compatibility
173+
gateway.instance_variable_set(:"@name", name)
174+
175+
gateways.add(name, gateway)
176+
end
146177
end
147178

148179
# @api private
149-
def default_adapter
150-
@default_adapter ||= adapter_for_gateway(default_gateway) || ROM.adapters.keys.first
180+
def load_config(config, hash)
181+
hash.each do |key, value|
182+
if value.is_a?(Hash)
183+
load_config(config[key], value)
184+
else
185+
config.send("#{key}=", value)
186+
end
187+
end
151188
end
152189

153-
private
154-
155190
# Returns gateway if method is a name of a registered gateway
156191
#
157192
# @return [Gateway]

lib/rom/constants.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def initialize(adapter, component)
2020
end
2121

2222
EnvAlreadyFinalizedError = Class.new(StandardError)
23+
GatewayAlreadyDefinedError = Class.new(StandardError)
2324
RelationAlreadyDefinedError = Class.new(StandardError)
2425
CommandAlreadyDefinedError = Class.new(StandardError)
2526
MapperAlreadyDefinedError = Class.new(StandardError)

lib/rom/environment.rb

Lines changed: 0 additions & 75 deletions
This file was deleted.

0 commit comments

Comments
 (0)