rom 5.3.2 → 6.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -47
- data/LICENSE +1 -1
- data/README.md +6 -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 +273 -36
@@ -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
|