rom 5.4.1 → 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 -65
- 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,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/components/core"
|
4
|
+
require "rom/components/dataset"
|
5
|
+
require "rom/components/relation"
|
6
|
+
require "rom/components/command"
|
7
|
+
|
8
|
+
module ROM
|
9
|
+
class Components::Core
|
10
|
+
# @api private
|
11
|
+
def trigger(event, payload)
|
12
|
+
registry.trigger("configuration.#{event}", payload)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
def notifications
|
17
|
+
registry.notifications
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Components::Dataset < Components::Core
|
22
|
+
mod = Module.new do
|
23
|
+
# @api private
|
24
|
+
def evaluate_block(ds, block)
|
25
|
+
if block.parameters.flatten.include?(:schema)
|
26
|
+
super
|
27
|
+
else
|
28
|
+
ds.instance_exec(relation_constant, &block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def relation_constant
|
33
|
+
registry.components.get(:relations, id: relation_id).constant
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
prepend(mod)
|
38
|
+
end
|
39
|
+
|
40
|
+
class Components::Relation < Components::Core
|
41
|
+
mod = Module.new do
|
42
|
+
def build
|
43
|
+
schema = local_components.get(:schemas, id: id)&.build
|
44
|
+
|
45
|
+
if schema
|
46
|
+
trigger(
|
47
|
+
"relations.schema.set",
|
48
|
+
schema: schema,
|
49
|
+
adapter: adapter,
|
50
|
+
gateway: config[:gateway],
|
51
|
+
relation: constant,
|
52
|
+
registry: registry
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
trigger("relations.class.ready", relation: constant, adapter: adapter)
|
57
|
+
|
58
|
+
components.update(local_components)
|
59
|
+
|
60
|
+
relation = super
|
61
|
+
|
62
|
+
trigger("relations.object.registered", registry: registry, relation: relation)
|
63
|
+
|
64
|
+
relation
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
prepend(mod)
|
69
|
+
end
|
70
|
+
|
71
|
+
class Components::Command < Components::Core
|
72
|
+
mod = Module.new do
|
73
|
+
def build
|
74
|
+
relation = registry.relations[config.relation]
|
75
|
+
|
76
|
+
trigger(
|
77
|
+
"commands.class.before_build",
|
78
|
+
command: constant,
|
79
|
+
gateway: registry.gateways[relation.gateway],
|
80
|
+
dataset: relation.dataset,
|
81
|
+
relation: relation,
|
82
|
+
adapter: adapter
|
83
|
+
)
|
84
|
+
|
85
|
+
super
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
prepend(mod)
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/container"
|
4
|
+
require "rom/global"
|
5
|
+
|
6
|
+
module ROM
|
7
|
+
# @api private
|
8
|
+
# @deprecated
|
9
|
+
alias_method :plugin_registry, :plugins
|
10
|
+
|
11
|
+
# @api public
|
12
|
+
module Global
|
13
|
+
# @api public
|
14
|
+
# @deprecated
|
15
|
+
alias_method :container, :setup
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/mapper"
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
class Mapper
|
7
|
+
class << self
|
8
|
+
prepend SettingProxy
|
9
|
+
|
10
|
+
def setting_mapping
|
11
|
+
@setting_mapper ||= ROM::Transformer.setting_mapping.merge(
|
12
|
+
inherit_header: [],
|
13
|
+
reject_keys: [],
|
14
|
+
symbolize_keys: [],
|
15
|
+
copy_keys: [],
|
16
|
+
prefix: [],
|
17
|
+
prefix_separator: []
|
18
|
+
).freeze
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/registries/root"
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
# @api public
|
7
|
+
class Registries::Root
|
8
|
+
option :notifications, optional: true
|
9
|
+
|
10
|
+
# @api private
|
11
|
+
# @api deprecated
|
12
|
+
def trigger(event, payload)
|
13
|
+
notifications&.trigger(event, payload)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @api public
|
17
|
+
# @deprecated
|
18
|
+
def map_with(*ids)
|
19
|
+
with(opts: {map_with: ids})
|
20
|
+
end
|
21
|
+
|
22
|
+
undef :build
|
23
|
+
# @api private
|
24
|
+
def build(key, &block)
|
25
|
+
item = components.(key, &block)
|
26
|
+
|
27
|
+
if commands? && (mappers = opts[:map_with])
|
28
|
+
item >> mappers.map { |mapper| item.relation.mappers[mapper] }.reduce(:>>)
|
29
|
+
else
|
30
|
+
item
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# @api private
|
37
|
+
def respond_to_missing?(name, *)
|
38
|
+
super || key?(name)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api public
|
42
|
+
# @deprecated
|
43
|
+
def method_missing(name, *args, &block)
|
44
|
+
fetch(name) { super }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/relation"
|
4
|
+
require_relative "schema/dsl"
|
5
|
+
|
6
|
+
module ROM
|
7
|
+
class Relation
|
8
|
+
class << self
|
9
|
+
prepend SettingProxy
|
10
|
+
|
11
|
+
def setting_mapping
|
12
|
+
@setting_mapping ||= {
|
13
|
+
auto_map: [],
|
14
|
+
auto_struct: [],
|
15
|
+
struct_namespace: [],
|
16
|
+
wrap_class: [],
|
17
|
+
adapter: [:component, :adapter],
|
18
|
+
gateway: [:component, :gateway],
|
19
|
+
schema_class: [:schema, :constant],
|
20
|
+
schema_dsl: [:schema, :dsl_class],
|
21
|
+
schema_attr_class: [:schema, :attr_class],
|
22
|
+
schema_inferrer: [:schema, :inferrer]
|
23
|
+
}.freeze
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
extend Notifications::Listener
|
28
|
+
|
29
|
+
# This is used by the deprecated command => relation view delegation syntax
|
30
|
+
# @api private
|
31
|
+
def self.view_methods
|
32
|
+
ancestor_methods = ancestors.reject { |klass| klass == self }
|
33
|
+
.map(&:instance_methods).flatten(1)
|
34
|
+
|
35
|
+
instance_methods - ancestor_methods + auto_curried_methods.to_a
|
36
|
+
end
|
37
|
+
|
38
|
+
config.schema.dsl_class = ROM::Schema::DSL
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,260 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/support/inflector"
|
4
|
+
|
5
|
+
require "rom/initializer"
|
6
|
+
require "rom/types"
|
7
|
+
require "rom/attribute"
|
8
|
+
require "rom/schema/associations_dsl"
|
9
|
+
|
10
|
+
module ROM
|
11
|
+
class Schema
|
12
|
+
# Schema DSL exposed as `schema { .. }` in relation classes
|
13
|
+
#
|
14
|
+
# @see Components::DSL::Schema
|
15
|
+
#
|
16
|
+
# @deprecated
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
class DSL
|
20
|
+
extend Initializer
|
21
|
+
|
22
|
+
# @!attribute [r] relation
|
23
|
+
# @return [Relation::Name] The name of the schema's relation
|
24
|
+
option :relation
|
25
|
+
|
26
|
+
# @!attribute [r] adapter
|
27
|
+
# @return [Symbol] The adapter identifier used in gateways
|
28
|
+
option :adapter
|
29
|
+
|
30
|
+
# @!attribute [r] inflector
|
31
|
+
# @return [Dry::Inflector] String inflector
|
32
|
+
# @api private
|
33
|
+
option :inflector, default: -> { Inflector }
|
34
|
+
|
35
|
+
# @!attribute [r] schema_class
|
36
|
+
# @return [Class] Schema class that should be instantiated
|
37
|
+
option :constant, default: -> { Schema }
|
38
|
+
alias_method :schema_class, :constant
|
39
|
+
|
40
|
+
# @!attribute [r] attr_class
|
41
|
+
# @return [Class] Attribute class that should be used
|
42
|
+
option :attr_class, default: -> { Attribute }
|
43
|
+
|
44
|
+
# @!attribute [r] attributes
|
45
|
+
# @return [Hash<Symbol, Hash>] A hash with attribute names as
|
46
|
+
# keys and attribute representations as values.
|
47
|
+
#
|
48
|
+
# @see [Schema.build_attribute_info]
|
49
|
+
option :attributes, default: -> { EMPTY_HASH.dup }
|
50
|
+
|
51
|
+
# @!attribute [r] definition
|
52
|
+
# @return [Class] An optional block that will be evaluated as part of this DSL
|
53
|
+
option :definition, type: Types.Instance(Proc), default: -> { proc {} }
|
54
|
+
|
55
|
+
# @!attribute [r] plugins
|
56
|
+
# @return [Array<Plugin>]
|
57
|
+
option :plugins, default: -> { EMPTY_ARRAY }
|
58
|
+
|
59
|
+
# @api private
|
60
|
+
def self.new(**options, &block)
|
61
|
+
if block
|
62
|
+
super(definition: block, **options)
|
63
|
+
else
|
64
|
+
super
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Defines a relation attribute with its type and options.
|
69
|
+
#
|
70
|
+
# When only options are given, type is left as nil. It makes
|
71
|
+
# sense when it is used alongside a schema inferrer, which will
|
72
|
+
# populate the type.
|
73
|
+
#
|
74
|
+
# @see Relation.schema
|
75
|
+
#
|
76
|
+
# @api public
|
77
|
+
def attribute(name, type_or_options, options = EMPTY_HASH)
|
78
|
+
if attributes.include?(name)
|
79
|
+
raise(
|
80
|
+
::ROM::AttributeAlreadyDefinedError,
|
81
|
+
"Attribute #{name.inspect} already defined"
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
build_attribute_info(name, type_or_options, options).tap do |attr_info|
|
86
|
+
attributes[name] = attr_info
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Specify which key(s) should be the primary key
|
91
|
+
#
|
92
|
+
# @api public
|
93
|
+
def primary_key(*names)
|
94
|
+
names.each do |name|
|
95
|
+
attributes[name][:type] = attributes[name][:type].meta(primary_key: true)
|
96
|
+
end
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
# Define associations for a relation
|
101
|
+
#
|
102
|
+
# @example
|
103
|
+
# class Users < ROM::Relation[:sql]
|
104
|
+
# schema(infer: true) do
|
105
|
+
# associations do
|
106
|
+
# has_many :tasks
|
107
|
+
# has_many :posts
|
108
|
+
# has_many :posts, as: :priority_posts, view: :prioritized
|
109
|
+
# belongs_to :account
|
110
|
+
# end
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
# class Posts < ROM::Relation[:sql]
|
115
|
+
# schema(infer: true) do
|
116
|
+
# associations do
|
117
|
+
# belongs_to :users, as: :author
|
118
|
+
# end
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# view(:prioritized) do
|
122
|
+
# where { priority <= 3 }
|
123
|
+
# end
|
124
|
+
# end
|
125
|
+
#
|
126
|
+
# @return [AssociationDSL]
|
127
|
+
#
|
128
|
+
# @api public
|
129
|
+
def associations(&block)
|
130
|
+
if block
|
131
|
+
__assoc_dsl__.instance_eval(&block)
|
132
|
+
else
|
133
|
+
__assoc_dsl__.registry.values
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# @api private
|
138
|
+
def __assoc_dsl__
|
139
|
+
@__assoc_dsl__ ||= AssociationsDSL.new(relation, inflector)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Enable a plugin in the schema DSL
|
143
|
+
#
|
144
|
+
# @param [Symbol] name Plugin name
|
145
|
+
# @param [Hash] options Plugin options
|
146
|
+
#
|
147
|
+
# @api public
|
148
|
+
def use(name, **options)
|
149
|
+
plugin = ::ROM.plugins[:schema].fetch(name, adapter).configure do |config|
|
150
|
+
config.update(options)
|
151
|
+
end
|
152
|
+
plugins << plugin.enable(self)
|
153
|
+
self
|
154
|
+
end
|
155
|
+
|
156
|
+
# @api public
|
157
|
+
def plugin(name, **options)
|
158
|
+
plugin = plugins.detect { |pl| pl.name == name }
|
159
|
+
plugin.config.update(options) unless options.empty?
|
160
|
+
plugin
|
161
|
+
end
|
162
|
+
|
163
|
+
# @api private
|
164
|
+
def call
|
165
|
+
schema_class.define(relation, **config)
|
166
|
+
end
|
167
|
+
|
168
|
+
# @api private
|
169
|
+
def config
|
170
|
+
@config ||=
|
171
|
+
begin
|
172
|
+
# Enable available plugin's
|
173
|
+
plugins.each do |plugin|
|
174
|
+
next unless plugin.type == :schema
|
175
|
+
plugin.enable(self) unless plugin.enabled?
|
176
|
+
end
|
177
|
+
|
178
|
+
# Apply custom definition block if it exists
|
179
|
+
instance_eval(&definition) if definition
|
180
|
+
|
181
|
+
# Apply plugin defaults
|
182
|
+
plugins.each do |plugin|
|
183
|
+
next unless plugin.type == :schema
|
184
|
+
plugin.__send__(:apply_to, self)
|
185
|
+
end
|
186
|
+
|
187
|
+
attributes.freeze
|
188
|
+
associations.freeze
|
189
|
+
|
190
|
+
opts.freeze
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# @api public
|
195
|
+
def inspect
|
196
|
+
%(<##{self.class} relation=#{relation} attributes=#{attributes} plugins=#{plugins}>)
|
197
|
+
end
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
# Return schema opts
|
202
|
+
#
|
203
|
+
# @return [Hash]
|
204
|
+
#
|
205
|
+
# @api private
|
206
|
+
def opts
|
207
|
+
{attributes: attributes.values,
|
208
|
+
associations: associations,
|
209
|
+
attr_class: attr_class,
|
210
|
+
plugins: plugins}
|
211
|
+
end
|
212
|
+
|
213
|
+
# Builds a representation of the information needed to create an
|
214
|
+
# attribute. It returns a hash with `:type` and `:options` keys.
|
215
|
+
#
|
216
|
+
# @return [Hash]
|
217
|
+
#
|
218
|
+
# @see [Schema.build_attribute_info]
|
219
|
+
#
|
220
|
+
# @api private
|
221
|
+
def build_attribute_info(name, type_or_options, options = EMPTY_HASH)
|
222
|
+
type, options = if type_or_options.is_a?(::Hash)
|
223
|
+
[nil, type_or_options]
|
224
|
+
else
|
225
|
+
[build_type(type_or_options, options), options]
|
226
|
+
end
|
227
|
+
Schema.build_attribute_info(
|
228
|
+
type, **options, name: name
|
229
|
+
)
|
230
|
+
end
|
231
|
+
|
232
|
+
# Builds a type instance from base type and meta options
|
233
|
+
#
|
234
|
+
# @return [Dry::Types::Type] Type instance
|
235
|
+
#
|
236
|
+
# @api private
|
237
|
+
def build_type(type, options = EMPTY_HASH)
|
238
|
+
meta = Attribute::META_OPTIONS
|
239
|
+
.map { |opt| [opt, options[opt]] if options.key?(opt) }
|
240
|
+
.compact
|
241
|
+
.to_h
|
242
|
+
|
243
|
+
base =
|
244
|
+
if options[:read]
|
245
|
+
type.meta(source: relation, read: options[:read])
|
246
|
+
elsif type.optional? && type.meta[:read]
|
247
|
+
type.meta(source: relation, read: type.meta[:read].optional)
|
248
|
+
else
|
249
|
+
type.meta(source: relation)
|
250
|
+
end
|
251
|
+
|
252
|
+
if meta.empty?
|
253
|
+
base
|
254
|
+
else
|
255
|
+
base.meta(meta)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/class_attributes"
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
module SettingProxy
|
7
|
+
extend Dry::Core::ClassAttributes
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# @api private
|
12
|
+
def respond_to_missing?(name, include_all = false)
|
13
|
+
super || setting_mapping.key?(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Delegate to config when accessing deprecated class attributes
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
def method_missing(name, *args, &block)
|
20
|
+
return super unless setting_mapping.key?(name)
|
21
|
+
|
22
|
+
mapping = setting_mapping[name]
|
23
|
+
ns, key = mapping
|
24
|
+
|
25
|
+
if args.empty?
|
26
|
+
if mapping.empty?
|
27
|
+
config[name]
|
28
|
+
else
|
29
|
+
config[ns][Array(key).first]
|
30
|
+
end
|
31
|
+
else
|
32
|
+
value = args.first
|
33
|
+
|
34
|
+
if mapping.empty?
|
35
|
+
config[name] = value
|
36
|
+
else
|
37
|
+
Array(key).each { |k| config[ns][k] = value }
|
38
|
+
end
|
39
|
+
|
40
|
+
value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/setup"
|
4
|
+
require "rom/support/notifications"
|
5
|
+
|
6
|
+
module ROM
|
7
|
+
# @api public
|
8
|
+
class Setup
|
9
|
+
extend Notifications
|
10
|
+
|
11
|
+
register_event("configuration.relations.class.ready")
|
12
|
+
register_event("configuration.relations.object.registered")
|
13
|
+
register_event("configuration.relations.registry.created")
|
14
|
+
register_event("configuration.relations.schema.allocated")
|
15
|
+
register_event("configuration.relations.schema.set")
|
16
|
+
register_event("configuration.relations.dataset.allocated")
|
17
|
+
register_event("configuration.commands.class.before_build")
|
18
|
+
|
19
|
+
mod = Module.new do
|
20
|
+
# @api public
|
21
|
+
def finalize
|
22
|
+
super { attach_listeners }
|
23
|
+
end
|
24
|
+
|
25
|
+
# @api private
|
26
|
+
def registry_options
|
27
|
+
super.merge(notifications: notifications)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
prepend(mod)
|
32
|
+
|
33
|
+
# @api public
|
34
|
+
# @deprecated
|
35
|
+
def notifications
|
36
|
+
@notifications ||= Notifications.event_bus(:configuration)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @api private
|
40
|
+
def attach_listeners
|
41
|
+
# Anything can attach globally to certain events, including plugins, so here
|
42
|
+
# we're making sure that only plugins that are enabled in this configuration
|
43
|
+
# will be triggered
|
44
|
+
global_listeners = Notifications.listeners.to_a
|
45
|
+
.reject { |(src, *)| plugin_registry.map(&:mod).include?(src) }.to_h
|
46
|
+
|
47
|
+
plugin_listeners = Notifications.listeners.to_a
|
48
|
+
.select { |(src, *)| plugins.map(&:mod).include?(src) }.to_h
|
49
|
+
|
50
|
+
listeners.update(global_listeners).update(plugin_listeners)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @api private
|
54
|
+
def listeners
|
55
|
+
notifications.listeners
|
56
|
+
end
|
57
|
+
|
58
|
+
# @api public
|
59
|
+
# @deprecated
|
60
|
+
def inflector=(inflector)
|
61
|
+
config.inflector = inflector
|
62
|
+
end
|
63
|
+
|
64
|
+
# Enable auto-registration for a given configuration object
|
65
|
+
#
|
66
|
+
# @param [String, Pathname] directory The root path to components
|
67
|
+
# @param [Hash] options
|
68
|
+
# @option options [Boolean, String] :namespace Toggle root namespace
|
69
|
+
# or provide a custom namespace name
|
70
|
+
#
|
71
|
+
# @return [Setup]
|
72
|
+
#
|
73
|
+
# @deprecated
|
74
|
+
#
|
75
|
+
# @see Configuration#auto_register
|
76
|
+
#
|
77
|
+
# @api public
|
78
|
+
def auto_registration(directory, **options)
|
79
|
+
auto_registration = AutoRegistration.new(directory, inflector: inflector, **options)
|
80
|
+
auto_registration.relations.each { |r| register_relation(r) }
|
81
|
+
auto_registration.commands.each { |r| register_command(r) }
|
82
|
+
auto_registration.mappers.each { |r| register_mapper(r) }
|
83
|
+
self
|
84
|
+
end
|
85
|
+
|
86
|
+
# @api private
|
87
|
+
# @deprecated
|
88
|
+
def relation_classes(gateway = nil)
|
89
|
+
if gateway
|
90
|
+
gid = gateway.is_a?(Symbol) ? gateway : gateway.config.id
|
91
|
+
components.relations.select { |r| r.config[:gateway] == gid }
|
92
|
+
else
|
93
|
+
components.relations
|
94
|
+
end.map(&:constant)
|
95
|
+
end
|
96
|
+
|
97
|
+
# @api public
|
98
|
+
# @deprecated
|
99
|
+
def command_classes
|
100
|
+
components.commands.map(&:constant)
|
101
|
+
end
|
102
|
+
|
103
|
+
# @api public
|
104
|
+
# @deprecated
|
105
|
+
def mapper_classes
|
106
|
+
components.mappers.map(&:constant)
|
107
|
+
end
|
108
|
+
|
109
|
+
# @api public
|
110
|
+
# @deprecated
|
111
|
+
def [](key)
|
112
|
+
gateways.fetch(key)
|
113
|
+
end
|
114
|
+
|
115
|
+
# @api public
|
116
|
+
# @deprecated
|
117
|
+
def gateways
|
118
|
+
@gateways ||=
|
119
|
+
begin
|
120
|
+
register_gateways
|
121
|
+
registry.gateways.map { |gateway| [gateway.config.id, gateway] }.to_h
|
122
|
+
end
|
123
|
+
end
|
124
|
+
alias_method :environment, :gateways
|
125
|
+
|
126
|
+
# @api private
|
127
|
+
# @deprecated
|
128
|
+
def gateways_map
|
129
|
+
@gateways_map ||= gateways.map(&:reverse).to_h
|
130
|
+
end
|
131
|
+
|
132
|
+
# @api private
|
133
|
+
def respond_to_missing?(name, include_all = false)
|
134
|
+
gateways.key?(name) || super
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
# Returns gateway if method is a name of a registered gateway
|
140
|
+
#
|
141
|
+
# @return [Gateway]
|
142
|
+
#
|
143
|
+
# @api public
|
144
|
+
# @deprecated
|
145
|
+
def method_missing(name, *)
|
146
|
+
gateways[name] || super
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
Configuration = Setup
|
151
|
+
end
|