rom 5.2.6 → 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 +60 -21
- 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,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
|