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,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/commands/composite"
|
4
|
+
require "rom/commands/graph"
|
5
|
+
|
6
|
+
module ROM
|
7
|
+
module Commands
|
8
|
+
# Lazy command wraps another command and evaluates its input when called
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class Lazy
|
12
|
+
include Dry::Equalizer(:command, :evaluator)
|
13
|
+
|
14
|
+
# @attr_reader [Command] command The wrapped command
|
15
|
+
attr_reader :command
|
16
|
+
|
17
|
+
alias_method :unwrap, :command
|
18
|
+
|
19
|
+
# @attr_reader [Proc] evaluator The proc that will evaluate the input
|
20
|
+
attr_reader :evaluator
|
21
|
+
|
22
|
+
attr_reader :command_proc
|
23
|
+
|
24
|
+
# @api private
|
25
|
+
def self.[](command)
|
26
|
+
case command
|
27
|
+
when Commands::Create then Lazy::Create
|
28
|
+
when Commands::Update then Lazy::Update
|
29
|
+
when Commands::Delete then Lazy::Delete
|
30
|
+
else
|
31
|
+
self
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
def initialize(command, evaluator, command_proc = nil)
|
37
|
+
@command = command
|
38
|
+
@evaluator = evaluator
|
39
|
+
@command_proc = command_proc || proc { |*| command }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Evaluate command's input using the input proc and pass to command
|
43
|
+
#
|
44
|
+
# @return [Array,Hash]
|
45
|
+
#
|
46
|
+
# @api public
|
47
|
+
def call(*_args)
|
48
|
+
raise NotImplementedError
|
49
|
+
end
|
50
|
+
|
51
|
+
# Compose a lazy command with another one
|
52
|
+
#
|
53
|
+
# @see Commands::Abstract#>>
|
54
|
+
#
|
55
|
+
# @return [Composite]
|
56
|
+
#
|
57
|
+
# @api public
|
58
|
+
def >>(other)
|
59
|
+
Composite.new(self, other)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Combine with other lazy commands
|
63
|
+
#
|
64
|
+
# @see Abstract#combine
|
65
|
+
#
|
66
|
+
# @return [Graph]
|
67
|
+
#
|
68
|
+
# @api public
|
69
|
+
def combine(*others)
|
70
|
+
Graph.new(self, others)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @api private
|
74
|
+
def lazy?
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
# @api private
|
79
|
+
def respond_to_missing?(name, include_private = false)
|
80
|
+
super || command.respond_to?(name)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# @api private
|
86
|
+
def method_missing(name, *args, &block)
|
87
|
+
if command.respond_to?(name)
|
88
|
+
response = command.public_send(name, *args, &block)
|
89
|
+
|
90
|
+
if response.instance_of?(command.class)
|
91
|
+
self.class.new(response, evaluator, command_proc)
|
92
|
+
else
|
93
|
+
response
|
94
|
+
end
|
95
|
+
else
|
96
|
+
super
|
97
|
+
end
|
98
|
+
end
|
99
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
require "rom/commands/lazy/create"
|
105
|
+
require "rom/commands/lazy/update"
|
106
|
+
require "rom/commands/lazy/delete"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/command"
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
module Commands
|
7
|
+
# Update command
|
8
|
+
#
|
9
|
+
# This command updates all tuples in its relation with new attributes
|
10
|
+
#
|
11
|
+
# @abstract
|
12
|
+
class Update < Command
|
13
|
+
config.restrictable = true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/rom/commands.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
require "rom/support/inflector"
|
6
|
+
|
7
|
+
require "rom/types"
|
8
|
+
require "rom/initializer"
|
9
|
+
|
10
|
+
require_relative "auto_registration_strategies/no_namespace"
|
11
|
+
require_relative "auto_registration_strategies/with_namespace"
|
12
|
+
require_relative "auto_registration_strategies/custom_namespace"
|
13
|
+
|
14
|
+
module ROM
|
15
|
+
# AutoRegistration is used to load component files automatically from the provided directory path
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
class AutoRegistration
|
19
|
+
extend Initializer
|
20
|
+
|
21
|
+
NamespaceType = Types::Strict::Bool | Types::Strict::String
|
22
|
+
|
23
|
+
PathnameType = Types.Constructor(Pathname, &Kernel.method(:Pathname))
|
24
|
+
|
25
|
+
InflectorType = Types.Strict(Dry::Inflector)
|
26
|
+
|
27
|
+
DEFAULT_MAPPING = {
|
28
|
+
relations: :relations,
|
29
|
+
mappers: :mappers,
|
30
|
+
commands: :commands
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
# @!attribute [r] directory
|
34
|
+
# @return [Pathname] The root path
|
35
|
+
param :directory, type: PathnameType
|
36
|
+
|
37
|
+
# @!attribute [r] namespace
|
38
|
+
# @return [Boolean,String]
|
39
|
+
# The name of the top level namespace or true/false which
|
40
|
+
# enables/disables default top level namespace inferred from the dir name
|
41
|
+
option :namespace, type: NamespaceType, default: -> { true }
|
42
|
+
|
43
|
+
# @!attribute [r] component_dirs
|
44
|
+
# @return [Hash] component => dir-name map
|
45
|
+
option :component_dirs, type: Types::Strict::Hash, default: -> { DEFAULT_MAPPING }
|
46
|
+
|
47
|
+
# @!attribute [r] globs
|
48
|
+
# @return [Hash] File globbing functions for each component dir
|
49
|
+
option :globs, default: lambda {
|
50
|
+
component_dirs.map { |component, path|
|
51
|
+
[component, directory.join("#{path}/**/*.rb")]
|
52
|
+
}.to_h
|
53
|
+
}
|
54
|
+
|
55
|
+
# @!attribute [r] inflector
|
56
|
+
# @return [Dry::Inflector] String inflector
|
57
|
+
# @api private
|
58
|
+
option :inflector, type: InflectorType, default: -> { Inflector }
|
59
|
+
|
60
|
+
# Load relation files
|
61
|
+
#
|
62
|
+
# @api private
|
63
|
+
def relations
|
64
|
+
load_entities(:relations)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Load command files
|
68
|
+
#
|
69
|
+
# @api private
|
70
|
+
def commands
|
71
|
+
load_entities(:commands)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Load mapper files
|
75
|
+
#
|
76
|
+
# @api private
|
77
|
+
def mappers
|
78
|
+
load_entities(:mappers)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Load given component files
|
84
|
+
#
|
85
|
+
# @api private
|
86
|
+
def load_entities(entity)
|
87
|
+
Dir[globs[entity]].sort.map do |file|
|
88
|
+
require file
|
89
|
+
klass_name =
|
90
|
+
case namespace
|
91
|
+
when String
|
92
|
+
AutoRegistrationStrategies::CustomNamespace.new(
|
93
|
+
namespace: namespace,
|
94
|
+
file: file,
|
95
|
+
directory: directory,
|
96
|
+
inflector: inflector
|
97
|
+
).call
|
98
|
+
when TrueClass
|
99
|
+
AutoRegistrationStrategies::WithNamespace.new(
|
100
|
+
file: file, directory: directory, inflector: inflector
|
101
|
+
).call
|
102
|
+
when FalseClass
|
103
|
+
AutoRegistrationStrategies::NoNamespace.new(
|
104
|
+
file: file,
|
105
|
+
directory: directory,
|
106
|
+
entity: component_dirs.fetch(entity),
|
107
|
+
inflector: inflector
|
108
|
+
).call
|
109
|
+
end
|
110
|
+
|
111
|
+
inflector.constantize(klass_name)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/types"
|
4
|
+
require "rom/initializer"
|
5
|
+
require "rom/support/inflector"
|
6
|
+
|
7
|
+
module ROM
|
8
|
+
module AutoRegistrationStrategies
|
9
|
+
# Base class for registration strategies
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
class Base
|
13
|
+
extend Initializer
|
14
|
+
|
15
|
+
PathnameType = Types.Instance(Pathname)
|
16
|
+
|
17
|
+
EXTENSION_REGEX = /\.rb\z/.freeze
|
18
|
+
|
19
|
+
# @!attribute [r] file
|
20
|
+
# @return [String] Name of a component file
|
21
|
+
option :file, type: Types::Strict::String
|
22
|
+
|
23
|
+
# @!attribute [r] inflector
|
24
|
+
# @return [Dry::Inflector] String inflector
|
25
|
+
# @api private
|
26
|
+
option :inflector, reader: true, default: -> { Inflector }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
require "rom/support/inflector"
|
6
|
+
require "rom/types"
|
7
|
+
|
8
|
+
require_relative "base"
|
9
|
+
|
10
|
+
module ROM
|
11
|
+
module AutoRegistrationStrategies
|
12
|
+
# Custom namespace strategy loads components and assumes they are defined
|
13
|
+
# within the provided namespace
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
class CustomNamespace < Base
|
17
|
+
# @!attribute [r] directory
|
18
|
+
# @return [Pathname] The path to dir with components
|
19
|
+
option :directory, type: PathnameType
|
20
|
+
|
21
|
+
# @!attribute [r] namespace
|
22
|
+
# @return [String] Name of a namespace
|
23
|
+
option :namespace, type: Types::Strict::String
|
24
|
+
|
25
|
+
# Loads components
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
def call
|
29
|
+
parts = path_arr.map { |part| inflector.camelize(part) }
|
30
|
+
potential = parts.map.with_index do |_, i|
|
31
|
+
parts[(i - parts.size)..parts.size]
|
32
|
+
end
|
33
|
+
attempted = []
|
34
|
+
|
35
|
+
potential.map do |path|
|
36
|
+
const_fragment = path.join("::")
|
37
|
+
|
38
|
+
constant = "#{namespace}::#{const_fragment}"
|
39
|
+
|
40
|
+
return constant if ns_const.const_defined?(const_fragment)
|
41
|
+
|
42
|
+
attempted << constant
|
43
|
+
end
|
44
|
+
|
45
|
+
# If we have reached this point, its means constant is not defined and
|
46
|
+
# NameError will be thrown if we attempt to camelize something like:
|
47
|
+
# `"#{namespace}::#{Inflector.camelize(filename)}"`
|
48
|
+
# so we can assume naming convention was not respected in required
|
49
|
+
# file.
|
50
|
+
|
51
|
+
raise NameError, name_error_message(attempted)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# @api private
|
57
|
+
def name_error_message(attempted)
|
58
|
+
"required file does not define expected constant name; either " \
|
59
|
+
"register your constant explicitly of try following the path" \
|
60
|
+
"naming convention like:\n\n\t- #{attempted.join("\n\t- ")}\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api private
|
64
|
+
def filename
|
65
|
+
Pathname(file).basename(".rb")
|
66
|
+
end
|
67
|
+
|
68
|
+
# @api private
|
69
|
+
def ns_const
|
70
|
+
@namespace_constant ||= inflector.constantize(namespace)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @api private
|
74
|
+
def path_arr
|
75
|
+
file_path << filename
|
76
|
+
end
|
77
|
+
|
78
|
+
# @api private
|
79
|
+
def file_path
|
80
|
+
File.dirname(file).split("/") - directory.to_s.split("/")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
require "rom/support/inflector"
|
6
|
+
require "rom/types"
|
7
|
+
require_relative "base"
|
8
|
+
|
9
|
+
module ROM
|
10
|
+
module AutoRegistrationStrategies
|
11
|
+
# NoNamespace strategy assumes components are not defined within a namespace
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
class NoNamespace < Base
|
15
|
+
# @!attribute [r] directory
|
16
|
+
# @return [Pathname] The path to dir with components
|
17
|
+
option :directory, type: PathnameType
|
18
|
+
|
19
|
+
# @!attribute [r] entity
|
20
|
+
# @return [Symbol] Component identifier
|
21
|
+
option :entity, type: Types::Strict::Symbol
|
22
|
+
|
23
|
+
# Load components
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
def call
|
27
|
+
inflector.camelize(
|
28
|
+
file.sub(%r{^#{directory}/#{entity}/}, "").sub(EXTENSION_REGEX, "")
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
require "rom/support/inflector"
|
6
|
+
require_relative "base"
|
7
|
+
|
8
|
+
module ROM
|
9
|
+
module AutoRegistrationStrategies
|
10
|
+
# WithNamespace strategy assumes components are defined within a namespace
|
11
|
+
# that matches top-level directory name.
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
class WithNamespace < Base
|
15
|
+
# @!attribute [r] directory
|
16
|
+
# @return [Pathname] The path to dir with components
|
17
|
+
option :directory, type: PathnameType
|
18
|
+
|
19
|
+
# Load components
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
def call
|
23
|
+
inflector.camelize(
|
24
|
+
file.sub(%r{^#{directory.dirname}/}, "").sub(EXTENSION_REGEX, "")
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/class_attributes"
|
4
|
+
require "rom/command"
|
5
|
+
|
6
|
+
module ROM
|
7
|
+
class Command
|
8
|
+
extend Dry::Core::ClassAttributes
|
9
|
+
|
10
|
+
module Restrictable
|
11
|
+
extend ROM::Notifications::Listener
|
12
|
+
|
13
|
+
subscribe("configuration.commands.class.before_build") do |event|
|
14
|
+
command = event[:command]
|
15
|
+
relation = event[:relation]
|
16
|
+
command.extend_for_relation(relation) if command.restrictable
|
17
|
+
end
|
18
|
+
|
19
|
+
# @api private
|
20
|
+
def create_class(relation: nil, **, &block)
|
21
|
+
klass = super
|
22
|
+
klass.extend_for_relation(relation) if relation && klass.restrictable
|
23
|
+
klass
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class << self
|
28
|
+
prepend Restrictable
|
29
|
+
prepend SettingProxy
|
30
|
+
|
31
|
+
def setting_mapping
|
32
|
+
@setting_mapper ||= {
|
33
|
+
adapter: [:component, :adapter],
|
34
|
+
relation: [:component, %i[relation namespace]],
|
35
|
+
register_as: [:component, :id],
|
36
|
+
restrictable: [],
|
37
|
+
result: [],
|
38
|
+
input: []
|
39
|
+
}.freeze
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Extend a command class with relation view methods
|
44
|
+
#
|
45
|
+
# @param [Relation] relation
|
46
|
+
#
|
47
|
+
# @return [Class]
|
48
|
+
#
|
49
|
+
# @api public
|
50
|
+
# @deprecated
|
51
|
+
def self.extend_for_relation(relation)
|
52
|
+
include(relation_methods_mod(relation.class))
|
53
|
+
end
|
54
|
+
|
55
|
+
# @api private
|
56
|
+
def self.relation_methods_mod(relation_class)
|
57
|
+
Module.new do
|
58
|
+
relation_class.view_methods.each do |meth|
|
59
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
60
|
+
def #{meth}(*args)
|
61
|
+
response = relation.public_send(:#{meth}, *args)
|
62
|
+
|
63
|
+
if response.is_a?(relation.class)
|
64
|
+
new(response)
|
65
|
+
else
|
66
|
+
response
|
67
|
+
end
|
68
|
+
end
|
69
|
+
RUBY
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom/relation/name"
|
4
|
+
|
5
|
+
require "rom/components/dsl/schema"
|
6
|
+
require "rom/compat/schema/dsl"
|
7
|
+
|
8
|
+
module ROM
|
9
|
+
module Components
|
10
|
+
module DSL
|
11
|
+
# @private
|
12
|
+
#
|
13
|
+
# rubocop:disable Metrics/AbcSize
|
14
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
15
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
16
|
+
class Schema < Core
|
17
|
+
mod = Module.new do
|
18
|
+
# @api private
|
19
|
+
def call
|
20
|
+
return super unless config.dsl_class || config.view
|
21
|
+
|
22
|
+
configure
|
23
|
+
|
24
|
+
if config.view
|
25
|
+
components.add(key, name: name, config: config, block: block)
|
26
|
+
else
|
27
|
+
dsl_config = backend.config
|
28
|
+
associations = dsl_config[:associations]
|
29
|
+
|
30
|
+
component = components.add(key, name: name, config: config.join(dsl_config, :right))
|
31
|
+
|
32
|
+
associations.each do |definition|
|
33
|
+
components.add(
|
34
|
+
:associations,
|
35
|
+
definition: definition,
|
36
|
+
config: dsl_assoc_config.join({namespace: relation, **definition.to_h}, :right)
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
component
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# @api public
|
45
|
+
#
|
46
|
+
# @deprecated
|
47
|
+
def associations(&block)
|
48
|
+
backend.associations(&block)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# @api private
|
54
|
+
def name
|
55
|
+
ROM::Relation::Name[relation, config.dataset]
|
56
|
+
end
|
57
|
+
|
58
|
+
# @api private
|
59
|
+
def dsl_assoc_config
|
60
|
+
provider.config.association.merge(adapter: adapter, inflector: inflector)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api private
|
64
|
+
def backend
|
65
|
+
@backend ||= config.dsl_class.new(
|
66
|
+
**config,
|
67
|
+
attributes: attributes,
|
68
|
+
inferrer: inferrer,
|
69
|
+
inflector: inflector,
|
70
|
+
plugins: config.plugins,
|
71
|
+
relation: name,
|
72
|
+
definition: block
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
# @api private
|
77
|
+
def configure
|
78
|
+
if !config.view && provider.config.component.type == :relation
|
79
|
+
provider.config.component.update(dataset: config.dataset) if config.dataset
|
80
|
+
provider.config.component.update(id: config.as) if config.as
|
81
|
+
|
82
|
+
if provider.config.component.id == :anonymous
|
83
|
+
provider.config.component.update(id: config.id)
|
84
|
+
end
|
85
|
+
|
86
|
+
if config.id.nil?
|
87
|
+
config.update(id: provider.config.component.id)
|
88
|
+
end
|
89
|
+
|
90
|
+
if config.relation.nil?
|
91
|
+
config.update(relation: provider.config.component.id)
|
92
|
+
end
|
93
|
+
|
94
|
+
if config.adapter.nil?
|
95
|
+
config.update(adapter: provider.config.component.adapter)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
config.update(id: relation) if relation && (config.id.nil? || config.as)
|
100
|
+
|
101
|
+
if provider.config.component.type == :relation
|
102
|
+
provider.config.component.inherit!(config)
|
103
|
+
end
|
104
|
+
|
105
|
+
if config.view
|
106
|
+
config.join!({namespace: relation}, :right)
|
107
|
+
end
|
108
|
+
|
109
|
+
super
|
110
|
+
end
|
111
|
+
|
112
|
+
# @api private
|
113
|
+
def relation
|
114
|
+
config.relation || config.as || config.id
|
115
|
+
end
|
116
|
+
|
117
|
+
# @api private
|
118
|
+
def inferrer
|
119
|
+
config.inferrer.with(enabled: config.infer)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
# rubocop:enable Metrics/AbcSize
|
123
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
124
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
125
|
+
|
126
|
+
prepend(mod)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|