rom 5.4.2 → 6.0.0.alpha1
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 +58 -71
- data/LICENSE +1 -1
- data/README.md +7 -6
- data/lib/rom/array_dataset.rb +46 -0
- data/lib/rom/associations/abstract.rb +217 -0
- data/lib/rom/associations/definitions/abstract.rb +150 -0
- data/lib/rom/associations/definitions/many_to_many.rb +29 -0
- data/lib/rom/associations/definitions/many_to_one.rb +14 -0
- data/lib/rom/associations/definitions/one_to_many.rb +14 -0
- data/lib/rom/associations/definitions/one_to_one.rb +14 -0
- data/lib/rom/associations/definitions/one_to_one_through.rb +14 -0
- data/lib/rom/associations/definitions.rb +7 -0
- data/lib/rom/associations/many_to_many.rb +128 -0
- data/lib/rom/associations/many_to_one.rb +65 -0
- data/lib/rom/associations/one_to_many.rb +65 -0
- data/lib/rom/associations/one_to_one.rb +13 -0
- data/lib/rom/associations/one_to_one_through.rb +13 -0
- data/lib/rom/associations/through_identifier.rb +41 -0
- data/lib/rom/attribute.rb +425 -0
- data/lib/rom/auto_curry.rb +70 -0
- data/lib/rom/cache.rb +87 -0
- data/lib/rom/changeset/associated.rb +110 -0
- data/lib/rom/changeset/create.rb +18 -0
- data/lib/rom/changeset/delete.rb +15 -0
- data/lib/rom/changeset/extensions/relation.rb +26 -0
- data/lib/rom/changeset/pipe.rb +81 -0
- data/lib/rom/changeset/pipe_registry.rb +27 -0
- data/lib/rom/changeset/stateful.rb +285 -0
- data/lib/rom/changeset/update.rb +81 -0
- data/lib/rom/changeset.rb +185 -0
- data/lib/rom/command.rb +351 -0
- data/lib/rom/command_compiler.rb +201 -0
- data/lib/rom/command_proxy.rb +36 -0
- data/lib/rom/commands/class_interface.rb +236 -0
- data/lib/rom/commands/composite.rb +55 -0
- data/lib/rom/commands/create.rb +15 -0
- data/lib/rom/commands/delete.rb +16 -0
- data/lib/rom/commands/graph/class_interface.rb +64 -0
- data/lib/rom/commands/graph/input_evaluator.rb +94 -0
- data/lib/rom/commands/graph.rb +88 -0
- data/lib/rom/commands/lazy/create.rb +35 -0
- data/lib/rom/commands/lazy/delete.rb +39 -0
- data/lib/rom/commands/lazy/update.rb +46 -0
- data/lib/rom/commands/lazy.rb +106 -0
- data/lib/rom/commands/update.rb +16 -0
- data/lib/rom/commands.rb +5 -0
- data/lib/rom/compat/auto_registration.rb +115 -0
- data/lib/rom/compat/auto_registration_strategies/base.rb +29 -0
- data/lib/rom/compat/auto_registration_strategies/custom_namespace.rb +84 -0
- data/lib/rom/compat/auto_registration_strategies/no_namespace.rb +33 -0
- data/lib/rom/compat/auto_registration_strategies/with_namespace.rb +29 -0
- data/lib/rom/compat/command.rb +74 -0
- data/lib/rom/compat/components/dsl/schema.rb +130 -0
- data/lib/rom/compat/components.rb +91 -0
- data/lib/rom/compat/global.rb +17 -0
- data/lib/rom/compat/mapper.rb +22 -0
- data/lib/rom/compat/registries.rb +47 -0
- data/lib/rom/compat/relation.rb +40 -0
- data/lib/rom/compat/schema/dsl.rb +260 -0
- data/lib/rom/compat/setting_proxy.rb +44 -0
- data/lib/rom/compat/setup.rb +151 -0
- data/lib/rom/compat/transformer.rb +49 -0
- data/lib/rom/compat.rb +22 -0
- data/lib/rom/components/association.rb +26 -0
- data/lib/rom/components/command.rb +24 -0
- data/lib/rom/components/core.rb +148 -0
- data/lib/rom/components/dataset.rb +60 -0
- data/lib/rom/components/dsl/association.rb +47 -0
- data/lib/rom/components/dsl/command.rb +60 -0
- data/lib/rom/components/dsl/core.rb +126 -0
- data/lib/rom/components/dsl/dataset.rb +33 -0
- data/lib/rom/components/dsl/gateway.rb +14 -0
- data/lib/rom/components/dsl/mapper.rb +70 -0
- data/lib/rom/components/dsl/relation.rb +49 -0
- data/lib/rom/components/dsl/schema.rb +150 -0
- data/lib/rom/components/dsl/view.rb +82 -0
- data/lib/rom/components/dsl.rb +255 -0
- data/lib/rom/components/gateway.rb +50 -0
- data/lib/rom/components/mapper.rb +29 -0
- data/lib/rom/components/provider.rb +160 -0
- data/lib/rom/components/registry.rb +154 -0
- data/lib/rom/components/relation.rb +41 -0
- data/lib/rom/components/schema.rb +61 -0
- data/lib/rom/components/view.rb +55 -0
- data/lib/rom/components.rb +55 -0
- data/lib/rom/configuration_dsl.rb +4 -0
- data/lib/rom/constants.rb +135 -0
- data/lib/rom/container.rb +182 -0
- data/lib/rom/core.rb +125 -0
- data/lib/rom/data_proxy.rb +97 -0
- data/lib/rom/enumerable_dataset.rb +70 -0
- data/lib/rom/gateway.rb +232 -0
- data/lib/rom/global.rb +56 -0
- data/lib/rom/header/attribute.rb +190 -0
- data/lib/rom/header.rb +198 -0
- data/lib/rom/inferrer.rb +55 -0
- data/lib/rom/initializer.rb +80 -0
- data/lib/rom/lint/enumerable_dataset.rb +56 -0
- data/lib/rom/lint/gateway.rb +120 -0
- data/lib/rom/lint/linter.rb +79 -0
- data/lib/rom/lint/spec.rb +22 -0
- data/lib/rom/lint/test.rb +98 -0
- data/lib/rom/loader.rb +161 -0
- data/lib/rom/mapper/attribute_dsl.rb +480 -0
- data/lib/rom/mapper/dsl.rb +107 -0
- data/lib/rom/mapper/model_dsl.rb +61 -0
- data/lib/rom/mapper.rb +99 -0
- data/lib/rom/mapper_compiler.rb +84 -0
- data/lib/rom/memory/associations/many_to_many.rb +12 -0
- data/lib/rom/memory/associations/many_to_one.rb +12 -0
- data/lib/rom/memory/associations/one_to_many.rb +12 -0
- data/lib/rom/memory/associations/one_to_one.rb +12 -0
- data/lib/rom/memory/associations.rb +6 -0
- data/lib/rom/memory/commands.rb +60 -0
- data/lib/rom/memory/dataset.rb +127 -0
- data/lib/rom/memory/gateway.rb +66 -0
- data/lib/rom/memory/mapper_compiler.rb +10 -0
- data/lib/rom/memory/relation.rb +91 -0
- data/lib/rom/memory/schema.rb +32 -0
- data/lib/rom/memory/storage.rb +61 -0
- data/lib/rom/memory/types.rb +11 -0
- data/lib/rom/memory.rb +7 -0
- data/lib/rom/model_builder.rb +103 -0
- data/lib/rom/open_struct.rb +112 -0
- data/lib/rom/pipeline.rb +111 -0
- data/lib/rom/plugin.rb +130 -0
- data/lib/rom/plugins/class_methods.rb +37 -0
- data/lib/rom/plugins/command/schema.rb +45 -0
- data/lib/rom/plugins/command/timestamps.rb +149 -0
- data/lib/rom/plugins/dsl.rb +53 -0
- data/lib/rom/plugins/relation/changeset.rb +97 -0
- data/lib/rom/plugins/relation/instrumentation.rb +66 -0
- data/lib/rom/plugins/relation/registry_reader.rb +36 -0
- data/lib/rom/plugins/schema/timestamps.rb +59 -0
- data/lib/rom/plugins.rb +100 -0
- data/lib/rom/processor/composer.rb +37 -0
- data/lib/rom/processor/transformer.rb +415 -0
- data/lib/rom/processor.rb +30 -0
- data/lib/rom/registries/associations.rb +26 -0
- data/lib/rom/registries/commands.rb +11 -0
- data/lib/rom/registries/container.rb +12 -0
- data/lib/rom/registries/datasets.rb +21 -0
- data/lib/rom/registries/gateways.rb +8 -0
- data/lib/rom/registries/mappers.rb +21 -0
- data/lib/rom/registries/nestable.rb +32 -0
- data/lib/rom/registries/relations.rb +8 -0
- data/lib/rom/registries/root.rb +203 -0
- data/lib/rom/registries/schemas.rb +44 -0
- data/lib/rom/registries/views.rb +11 -0
- data/lib/rom/relation/class_interface.rb +61 -0
- data/lib/rom/relation/combined.rb +160 -0
- data/lib/rom/relation/commands.rb +65 -0
- data/lib/rom/relation/composite.rb +53 -0
- data/lib/rom/relation/curried.rb +129 -0
- data/lib/rom/relation/graph.rb +107 -0
- data/lib/rom/relation/loaded.rb +136 -0
- data/lib/rom/relation/materializable.rb +62 -0
- data/lib/rom/relation/name.rb +122 -0
- data/lib/rom/relation/wrap.rb +64 -0
- data/lib/rom/relation.rb +625 -0
- data/lib/rom/repository/class_interface.rb +162 -0
- data/lib/rom/repository/relation_reader.rb +48 -0
- data/lib/rom/repository/root.rb +75 -0
- data/lib/rom/repository/session.rb +60 -0
- data/lib/rom/repository.rb +179 -0
- data/lib/rom/schema/associations_dsl.rb +222 -0
- data/lib/rom/schema/inferrer.rb +106 -0
- data/lib/rom/schema.rb +471 -0
- data/lib/rom/settings.rb +141 -0
- data/lib/rom/setup.rb +297 -0
- data/lib/rom/struct.rb +99 -0
- data/lib/rom/struct_compiler.rb +114 -0
- data/lib/rom/support/configurable.rb +213 -0
- data/lib/rom/support/inflector.rb +31 -0
- data/lib/rom/support/memoizable.rb +61 -0
- data/lib/rom/support/notifications.rb +238 -0
- data/lib/rom/transaction.rb +26 -0
- data/lib/rom/transformer.rb +46 -0
- data/lib/rom/types.rb +74 -0
- data/lib/rom/version.rb +1 -1
- data/lib/rom-changeset.rb +4 -0
- data/lib/rom-core.rb +3 -0
- data/lib/rom-repository.rb +4 -0
- data/lib/rom.rb +3 -3
- metadata +302 -23
@@ -0,0 +1,160 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/support/configurable"
|
4
|
+
|
5
|
+
require "rom/core"
|
6
|
+
require "rom/settings"
|
7
|
+
require "rom/registries/root"
|
8
|
+
|
9
|
+
require_relative "dsl"
|
10
|
+
require_relative "registry"
|
11
|
+
|
12
|
+
module ROM
|
13
|
+
# Define a module for component definitions and runtime setup
|
14
|
+
#
|
15
|
+
# @return [Components::Provider]
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
def self.Provider(*features, **options)
|
19
|
+
Components::Provider.new(features, **options)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @api private
|
23
|
+
module Components
|
24
|
+
# @api private
|
25
|
+
class Provider < Module
|
26
|
+
attr_reader :provider
|
27
|
+
|
28
|
+
attr_reader :type
|
29
|
+
|
30
|
+
attr_reader :features
|
31
|
+
|
32
|
+
# @api private
|
33
|
+
module InstanceMethods
|
34
|
+
# @api public
|
35
|
+
def components
|
36
|
+
@components ||= Registry.new(provider: self)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @api private
|
40
|
+
def registry(**options)
|
41
|
+
Registries::Root.new(
|
42
|
+
config: config,
|
43
|
+
components: components,
|
44
|
+
notifications: Notifications.event_bus(:configuration),
|
45
|
+
**options
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# @api private
|
51
|
+
module ClassMethods
|
52
|
+
include InstanceMethods
|
53
|
+
|
54
|
+
# @api private
|
55
|
+
def inherited(klass)
|
56
|
+
super
|
57
|
+
klass.components.update(components, abstract: true)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# @api private
|
62
|
+
def initialize(features, type: nil)
|
63
|
+
super()
|
64
|
+
@provider = nil
|
65
|
+
@type = type
|
66
|
+
@features = features
|
67
|
+
end
|
68
|
+
|
69
|
+
# @api private
|
70
|
+
def define_configure_method(type, features)
|
71
|
+
yield Module.new {
|
72
|
+
define_method(:configure) do |*args, &block|
|
73
|
+
# Inherit global defaults
|
74
|
+
config.component.inherit!(**ROM.config[type], type: type)
|
75
|
+
|
76
|
+
# Inherit global defaults for individual features
|
77
|
+
features.each do |name|
|
78
|
+
config[name].inherit!(**ROM.config[name]) if ROM.config.key?(name)
|
79
|
+
end
|
80
|
+
|
81
|
+
super(*args, &block)
|
82
|
+
end
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
# @api private
|
87
|
+
def included(provider)
|
88
|
+
super
|
89
|
+
@provider = provider
|
90
|
+
provider.include(mod)
|
91
|
+
provider.include(Configurable)
|
92
|
+
import_settings
|
93
|
+
provider.include(InstanceMethods)
|
94
|
+
define_configure_method(type, features) { |mod|
|
95
|
+
provider.prepend(mod)
|
96
|
+
}
|
97
|
+
freeze
|
98
|
+
end
|
99
|
+
|
100
|
+
# @api private
|
101
|
+
def extended(provider)
|
102
|
+
super
|
103
|
+
@provider = provider
|
104
|
+
provider.extend(mod)
|
105
|
+
provider.extend(Configurable)
|
106
|
+
import_settings
|
107
|
+
provider.extend(ClassMethods)
|
108
|
+
define_configure_method(type, features) { |mod|
|
109
|
+
provider.singleton_class.prepend(mod)
|
110
|
+
}
|
111
|
+
freeze
|
112
|
+
end
|
113
|
+
|
114
|
+
# @api private
|
115
|
+
def mod
|
116
|
+
@mod ||=
|
117
|
+
Module.new.tap do |mod|
|
118
|
+
define_dsl_method(mod, :__dsl__)
|
119
|
+
|
120
|
+
features.each do |type|
|
121
|
+
if ROM.components.key?(type)
|
122
|
+
handler = ROM.components[type]
|
123
|
+
|
124
|
+
[handler.key, handler.namespace]
|
125
|
+
.select { |name|
|
126
|
+
DSL.instance_methods.include?(name)
|
127
|
+
}
|
128
|
+
.each { |name|
|
129
|
+
define_dsl_method(mod, name)
|
130
|
+
}
|
131
|
+
else
|
132
|
+
define_dsl_method(mod, type)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# @api private
|
139
|
+
def define_dsl_method(mod, name)
|
140
|
+
mod.define_method(name) { |*args, **opts, &block|
|
141
|
+
DSL.instance_method(name).bind(self).(*args, **opts, &block)
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
# @api private
|
146
|
+
def import_settings
|
147
|
+
# Import default settings for the provider
|
148
|
+
provider.setting(:component, import: ROM.settings[type])
|
149
|
+
|
150
|
+
# Import default settings for each feature that the provider supports
|
151
|
+
features.each do |name|
|
152
|
+
if ROM.settings.key?(name)
|
153
|
+
# Define the settings
|
154
|
+
provider.setting(name, import: ROM.settings[name])
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/constants"
|
4
|
+
require "rom/core"
|
5
|
+
|
6
|
+
module ROM
|
7
|
+
# @api private
|
8
|
+
module Components
|
9
|
+
# @api public
|
10
|
+
class Registry
|
11
|
+
include Enumerable
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
attr_reader :provider
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
attr_reader :handlers
|
18
|
+
|
19
|
+
DUPLICATE_ERRORS = {
|
20
|
+
gateways: GatewayAlreadyDefinedError,
|
21
|
+
datasets: DatasetAlreadyDefinedError,
|
22
|
+
schemas: SchemaAlreadyDefinedError,
|
23
|
+
relations: RelationAlreadyDefinedError,
|
24
|
+
associations: AssociationAlreadyDefinedError,
|
25
|
+
commands: CommandAlreadyDefinedError,
|
26
|
+
mappers: MapperAlreadyDefinedError
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
def initialize(provider:, handlers: ROM.components)
|
31
|
+
@provider = provider
|
32
|
+
@handlers = handlers
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
def store
|
37
|
+
@store ||= handlers.map { |handler| [handler.namespace, EMPTY_ARRAY.dup] }.to_h
|
38
|
+
end
|
39
|
+
|
40
|
+
# @api private
|
41
|
+
def each
|
42
|
+
store.each { |type, components|
|
43
|
+
components.each { |component| yield(type, component) }
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
# @api private
|
48
|
+
def to_a
|
49
|
+
flat_map { |_, components| components }
|
50
|
+
end
|
51
|
+
|
52
|
+
# @api private
|
53
|
+
def call(key, &fallback)
|
54
|
+
comp = detect { |_, component| component.key == key && !component.abstract? }&.last
|
55
|
+
|
56
|
+
if comp
|
57
|
+
comp.build
|
58
|
+
elsif fallback
|
59
|
+
fallback.()
|
60
|
+
else
|
61
|
+
raise KeyError, "+#{key}+ not found"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# @api private
|
66
|
+
def [](type)
|
67
|
+
store[type]
|
68
|
+
end
|
69
|
+
|
70
|
+
# @api private
|
71
|
+
def get(type, **opts)
|
72
|
+
public_send(type, **opts).first
|
73
|
+
end
|
74
|
+
|
75
|
+
# @api private
|
76
|
+
def add(type, item: nil, **options)
|
77
|
+
component = item || build(type, **options)
|
78
|
+
|
79
|
+
# if include?(type, component)
|
80
|
+
# other = get(type, key: component.key)
|
81
|
+
|
82
|
+
# raise(
|
83
|
+
# DUPLICATE_ERRORS[type],
|
84
|
+
# "#{provider}: +#{component.key}+ is already defined by #{other.provider}"
|
85
|
+
# )
|
86
|
+
# end
|
87
|
+
|
88
|
+
store[type] << component
|
89
|
+
|
90
|
+
update(component.local_components)
|
91
|
+
|
92
|
+
component
|
93
|
+
end
|
94
|
+
|
95
|
+
# @api private
|
96
|
+
def replace(type, item: nil, **options)
|
97
|
+
component = item || build(type, **options)
|
98
|
+
delete(type, item) if include?(type, component)
|
99
|
+
store[type] << component
|
100
|
+
component
|
101
|
+
end
|
102
|
+
|
103
|
+
# @api private
|
104
|
+
def delete(type, item)
|
105
|
+
self[type].delete(item)
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
# @api private
|
110
|
+
def update(other, **options)
|
111
|
+
other.each do |type, component|
|
112
|
+
add(
|
113
|
+
type,
|
114
|
+
item: component.with(provider: provider, config: component.config.join(options, :right))
|
115
|
+
)
|
116
|
+
end
|
117
|
+
self
|
118
|
+
end
|
119
|
+
|
120
|
+
# @api private
|
121
|
+
def build(type, **options)
|
122
|
+
handlers[type].build(**options, provider: provider)
|
123
|
+
end
|
124
|
+
|
125
|
+
# @api private
|
126
|
+
def include?(type, component)
|
127
|
+
!component.abstract? && keys(type).include?(component.key)
|
128
|
+
end
|
129
|
+
|
130
|
+
# @api private
|
131
|
+
def key?(key)
|
132
|
+
keys.include?(key)
|
133
|
+
end
|
134
|
+
|
135
|
+
# @api private
|
136
|
+
def keys(type = nil)
|
137
|
+
if type
|
138
|
+
self[type].map(&:key)
|
139
|
+
else
|
140
|
+
to_a.map(&:key)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
CORE_COMPONENTS.each do |type|
|
145
|
+
define_method(type) do |**opts|
|
146
|
+
all = self[type]
|
147
|
+
return all if opts.empty?
|
148
|
+
|
149
|
+
all.select { |el| opts.all? { |key, value| el.public_send(key).eql?(value) } }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "core"
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
module Components
|
7
|
+
# @api public
|
8
|
+
class Relation < Core
|
9
|
+
# @!attribute [r] constant
|
10
|
+
# @return [.new] Relation instance builder (typically a class)
|
11
|
+
option :constant, type: Types.Interface(:new)
|
12
|
+
|
13
|
+
# @return [ROM::Relation]
|
14
|
+
#
|
15
|
+
# @api public
|
16
|
+
def build
|
17
|
+
constant.use(:changeset)
|
18
|
+
constant.use(:registry_reader, relations: registry.relation_ids)
|
19
|
+
|
20
|
+
# Define view methods if there are any registered view components for this relation
|
21
|
+
local_components.views(relation_id: id).each do |view|
|
22
|
+
view.define(constant)
|
23
|
+
end
|
24
|
+
|
25
|
+
apply_plugins
|
26
|
+
|
27
|
+
constant.new(inflector: inflector, registry: registry, **plugin_options)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @api public
|
31
|
+
def adapter
|
32
|
+
config.adapter
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
def local_components
|
37
|
+
constant.components
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/relation/name"
|
4
|
+
|
5
|
+
require_relative "core"
|
6
|
+
|
7
|
+
module ROM
|
8
|
+
module Components
|
9
|
+
# @api public
|
10
|
+
class Schema < Core
|
11
|
+
# @api private
|
12
|
+
option :name, type: Types.Instance(ROM::Relation::Name), default: -> {
|
13
|
+
ROM::Relation::Name[config.relation, config.dataset]
|
14
|
+
}
|
15
|
+
|
16
|
+
# @api public
|
17
|
+
def build
|
18
|
+
if view?
|
19
|
+
registry.schemas[config.relation].instance_eval(&block)
|
20
|
+
else
|
21
|
+
schema = config.constant.define(
|
22
|
+
name, **config, **config.options, inferrer: inferrer, registry: registry
|
23
|
+
)
|
24
|
+
|
25
|
+
if gateway?
|
26
|
+
schema.finalize_attributes!(gateway: gateway)
|
27
|
+
else
|
28
|
+
schema.finalize_attributes!
|
29
|
+
end
|
30
|
+
|
31
|
+
schema.finalize!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
def inferrer
|
37
|
+
config.inferrer.with(enabled: config.infer)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @api private
|
41
|
+
def dataset
|
42
|
+
config.dataset
|
43
|
+
end
|
44
|
+
|
45
|
+
# @api private
|
46
|
+
def adapter
|
47
|
+
config.adapter
|
48
|
+
end
|
49
|
+
|
50
|
+
# @api private
|
51
|
+
def relation
|
52
|
+
config.relation
|
53
|
+
end
|
54
|
+
|
55
|
+
# @api private
|
56
|
+
def view?
|
57
|
+
config.view.equal?(true)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "core"
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
module Components
|
7
|
+
# @api public
|
8
|
+
class View < Core
|
9
|
+
# @!attribute [r] relation_id
|
10
|
+
# @return [Symbol] Relation runtime identifier
|
11
|
+
# @api private
|
12
|
+
option :relation_id
|
13
|
+
|
14
|
+
# @!attribute [r] relation_block
|
15
|
+
# @return [Proc] Block used for view method definition
|
16
|
+
# @api private
|
17
|
+
option :relation_block
|
18
|
+
|
19
|
+
# @return [ROM::Relation]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
def build
|
23
|
+
registry.relations[relation_id].public_send(config.id)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Symbol]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
def define(constant)
|
30
|
+
_name = config.id
|
31
|
+
_relation_block = relation_block
|
32
|
+
|
33
|
+
if relation_block&.arity&.positive?
|
34
|
+
constant.class_eval do
|
35
|
+
auto_curry_guard do
|
36
|
+
define_method(_name, &_relation_block)
|
37
|
+
|
38
|
+
auto_curry(_name) do
|
39
|
+
schemas[_name].(self)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
else
|
44
|
+
constant.class_eval do
|
45
|
+
define_method(_name) do
|
46
|
+
schemas[_name].(instance_eval(&_relation_block))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
_name
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/container"
|
4
|
+
|
5
|
+
require_relative "initializer"
|
6
|
+
require_relative "types"
|
7
|
+
|
8
|
+
module ROM
|
9
|
+
# Registry of all known component handlers
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
module Components
|
13
|
+
extend Dry::Container::Mixin
|
14
|
+
extend Enumerable
|
15
|
+
|
16
|
+
module_function
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
class Handler
|
20
|
+
extend Initializer
|
21
|
+
|
22
|
+
option :key, type: Types.Instance(Symbol)
|
23
|
+
|
24
|
+
option :constant, type: Types.Interface(:new)
|
25
|
+
|
26
|
+
option :namespace, type: Types.Instance(Symbol), default: -> { Inflector.namespace(key) }
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def build(**options)
|
30
|
+
constant.new(**options)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @see ROM.components
|
35
|
+
#
|
36
|
+
# @return [Components]
|
37
|
+
#
|
38
|
+
# @api public
|
39
|
+
def register(key, constant = nil, **options)
|
40
|
+
Handler.new(key: key, constant: constant, **options).tap do |handler|
|
41
|
+
super(handler.key, handler)
|
42
|
+
# TODO: unify handler access
|
43
|
+
super(handler.namespace, handler)
|
44
|
+
end
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
# Iterate over all registered component handlers
|
49
|
+
#
|
50
|
+
# @api public
|
51
|
+
def each
|
52
|
+
keys.each { |key| yield(resolve(key)) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/constants"
|
4
|
+
|
5
|
+
# Constants and errors common in the whole library
|
6
|
+
module ROM
|
7
|
+
include Dry::Core::Constants
|
8
|
+
|
9
|
+
CORE_COMPONENTS = %i[
|
10
|
+
gateways
|
11
|
+
datasets
|
12
|
+
schemas
|
13
|
+
relations
|
14
|
+
views
|
15
|
+
associations
|
16
|
+
mappers
|
17
|
+
commands
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
AdapterLoadError = Class.new(StandardError)
|
21
|
+
|
22
|
+
# Exception raised when a component is configured with an adapter that's not loaded
|
23
|
+
class AdapterNotPresentError < StandardError
|
24
|
+
# @api private
|
25
|
+
def initialize(adapter, component)
|
26
|
+
super(
|
27
|
+
"Failed to find #{component} class for #{adapter} adapter. " \
|
28
|
+
"Make sure ROM setup was started and the adapter identifier is correct."
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
ConfigError = Class.new(StandardError) do
|
34
|
+
attr_reader :name, :component, :owner
|
35
|
+
|
36
|
+
# @api private
|
37
|
+
def initialize(name, component, reason = :inferrence)
|
38
|
+
@name = name
|
39
|
+
@component = component
|
40
|
+
@owner = component.owner
|
41
|
+
|
42
|
+
key = "#{component.type}.#{name}"
|
43
|
+
|
44
|
+
case reason
|
45
|
+
when :inferrence
|
46
|
+
super("Failed to infer +#{key}+ setting for #{component.provider}")
|
47
|
+
else
|
48
|
+
super("#{owner.name} #{key} setting is not valid")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
EnvAlreadyFinalizedError = Class.new(StandardError)
|
54
|
+
GatewayAlreadyDefinedError = Class.new(StandardError)
|
55
|
+
DatasetAlreadyDefinedError = Class.new(StandardError)
|
56
|
+
SchemaAlreadyDefinedError = Class.new(StandardError)
|
57
|
+
RelationAlreadyDefinedError = Class.new(StandardError)
|
58
|
+
AssociationAlreadyDefinedError = Class.new(StandardError)
|
59
|
+
CommandAlreadyDefinedError = Class.new(StandardError)
|
60
|
+
MapperAlreadyDefinedError = Class.new(StandardError)
|
61
|
+
MapperMisconfiguredError = Class.new(StandardError)
|
62
|
+
NoRelationError = Class.new(StandardError)
|
63
|
+
InvalidRelationName = Class.new(StandardError)
|
64
|
+
CommandError = Class.new(StandardError)
|
65
|
+
KeyMissing = Class.new(ROM::CommandError)
|
66
|
+
TupleCountMismatchError = Class.new(CommandError)
|
67
|
+
UnknownPluginError = Class.new(StandardError)
|
68
|
+
UnsupportedRelationError = Class.new(StandardError)
|
69
|
+
MissingAdapterIdentifierError = Class.new(StandardError)
|
70
|
+
AttributeAlreadyDefinedError = Class.new(StandardError)
|
71
|
+
|
72
|
+
# Exception raised when a reserved keyword is used as a relation name
|
73
|
+
class InvalidRelationName < StandardError
|
74
|
+
# @api private
|
75
|
+
def initialize(relation)
|
76
|
+
super("Relation name: #{relation} is a protected word, please use another relation name")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Exception raised when an element inside a component registry is not found
|
81
|
+
class ElementNotFoundError < KeyError
|
82
|
+
# @api private
|
83
|
+
def initialize(key, registry = nil)
|
84
|
+
msg =
|
85
|
+
if registry
|
86
|
+
"#{key.inspect} doesn't exist in #{registry.type} registry"
|
87
|
+
else
|
88
|
+
"#{key} doesn't exist in the registry"
|
89
|
+
end
|
90
|
+
super(msg)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
GatewayMissingError = Class.new(ElementNotFoundError)
|
95
|
+
|
96
|
+
DatasetMissingError = Class.new(ElementNotFoundError)
|
97
|
+
|
98
|
+
SchemaMissingError = Class.new(ElementNotFoundError)
|
99
|
+
|
100
|
+
RelationMissingError = Class.new(ElementNotFoundError)
|
101
|
+
|
102
|
+
MapperMissingError = Class.new(ElementNotFoundError)
|
103
|
+
|
104
|
+
CommandNotFoundError = Class.new(ElementNotFoundError)
|
105
|
+
|
106
|
+
MissingSchemaClassError = Class.new(StandardError) do
|
107
|
+
# @api private
|
108
|
+
def initialize(klass)
|
109
|
+
super("#{klass.inspect} relation is missing schema_class")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
MissingSchemaError = Class.new(StandardError) do
|
114
|
+
# @api private
|
115
|
+
def initialize(klass)
|
116
|
+
super("#{klass.inspect} relation is missing schema definition")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
MISSING_ELEMENT_ERRORS = {
|
121
|
+
gateways: GatewayMissingError,
|
122
|
+
schemas: SchemaMissingError,
|
123
|
+
datasets: DatasetMissingError,
|
124
|
+
relations: RelationMissingError,
|
125
|
+
associations: RelationMissingError,
|
126
|
+
commands: CommandNotFoundError,
|
127
|
+
mappers: MapperMissingError
|
128
|
+
}.freeze
|
129
|
+
|
130
|
+
DuplicateConfigurationError = Class.new(StandardError)
|
131
|
+
DuplicateContainerError = Class.new(StandardError)
|
132
|
+
|
133
|
+
InvalidOptionValueError = Class.new(StandardError)
|
134
|
+
InvalidOptionKeyError = Class.new(StandardError)
|
135
|
+
end
|