rom-core 4.2.1 → 5.0.0
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/README.md +0 -2
- data/lib/rom-core.rb +2 -0
- data/lib/rom/array_dataset.rb +2 -0
- data/lib/rom/association_set.rb +2 -0
- data/lib/rom/associations/abstract.rb +2 -0
- data/lib/rom/associations/definitions.rb +2 -0
- data/lib/rom/associations/definitions/abstract.rb +2 -0
- data/lib/rom/associations/definitions/many_to_many.rb +2 -0
- data/lib/rom/associations/definitions/many_to_one.rb +2 -0
- data/lib/rom/associations/definitions/one_to_many.rb +2 -0
- data/lib/rom/associations/definitions/one_to_one.rb +2 -0
- data/lib/rom/associations/definitions/one_to_one_through.rb +2 -0
- data/lib/rom/associations/many_to_many.rb +2 -0
- data/lib/rom/associations/many_to_one.rb +2 -0
- data/lib/rom/associations/one_to_many.rb +2 -0
- data/lib/rom/associations/one_to_one.rb +2 -0
- data/lib/rom/associations/one_to_one_through.rb +2 -0
- data/lib/rom/associations/through_identifier.rb +2 -0
- data/lib/rom/attribute.rb +58 -72
- data/lib/rom/auto_curry.rb +2 -0
- data/lib/rom/cache.rb +2 -0
- data/lib/rom/command.rb +7 -5
- data/lib/rom/command_compiler.rb +2 -0
- data/lib/rom/command_proxy.rb +2 -0
- data/lib/rom/command_registry.rb +13 -7
- data/lib/rom/commands.rb +2 -0
- data/lib/rom/commands/class_interface.rb +4 -2
- data/lib/rom/commands/composite.rb +2 -0
- data/lib/rom/commands/create.rb +2 -0
- data/lib/rom/commands/delete.rb +2 -0
- data/lib/rom/commands/graph.rb +2 -0
- data/lib/rom/commands/graph/class_interface.rb +2 -0
- data/lib/rom/commands/graph/input_evaluator.rb +2 -0
- data/lib/rom/commands/lazy.rb +2 -0
- data/lib/rom/commands/lazy/create.rb +2 -0
- data/lib/rom/commands/lazy/delete.rb +2 -0
- data/lib/rom/commands/lazy/update.rb +2 -0
- data/lib/rom/commands/update.rb +2 -0
- data/lib/rom/configuration.rb +2 -0
- data/lib/rom/configuration_dsl.rb +2 -0
- data/lib/rom/configuration_dsl/command.rb +2 -0
- data/lib/rom/configuration_dsl/command_dsl.rb +2 -0
- data/lib/rom/configuration_dsl/relation.rb +2 -0
- data/lib/rom/configuration_plugin.rb +2 -0
- data/lib/rom/constants.rb +3 -0
- data/lib/rom/container.rb +2 -0
- data/lib/rom/core.rb +4 -1
- data/lib/rom/create_container.rb +2 -0
- data/lib/rom/data_proxy.rb +2 -0
- data/lib/rom/enumerable_dataset.rb +2 -0
- data/lib/rom/environment.rb +2 -0
- data/lib/rom/gateway.rb +2 -0
- data/lib/rom/global.rb +2 -0
- data/lib/rom/global/plugin_dsl.rb +2 -0
- data/lib/rom/header.rb +198 -0
- data/lib/rom/header/attribute.rb +192 -0
- data/lib/rom/initializer.rb +2 -0
- data/lib/rom/lint/enumerable_dataset.rb +2 -0
- data/lib/rom/lint/gateway.rb +2 -0
- data/lib/rom/lint/linter.rb +2 -0
- data/lib/rom/lint/spec.rb +2 -0
- data/lib/rom/lint/test.rb +2 -0
- data/lib/rom/mapper.rb +100 -0
- data/lib/rom/mapper/attribute_dsl.rb +480 -0
- data/lib/rom/mapper/builder.rb +39 -0
- data/lib/rom/mapper/configuration_plugin.rb +28 -0
- data/lib/rom/mapper/dsl.rb +123 -0
- data/lib/rom/mapper/mapper_dsl.rb +45 -0
- data/lib/rom/mapper/model_dsl.rb +60 -0
- data/lib/rom/mapper_compiler.rb +84 -0
- data/lib/rom/mapper_registry.rb +2 -0
- data/lib/rom/memory.rb +2 -0
- data/lib/rom/memory/associations.rb +2 -0
- data/lib/rom/memory/associations/many_to_many.rb +2 -0
- data/lib/rom/memory/associations/many_to_one.rb +2 -0
- data/lib/rom/memory/associations/one_to_many.rb +2 -0
- data/lib/rom/memory/associations/one_to_one.rb +2 -0
- data/lib/rom/memory/commands.rb +2 -0
- data/lib/rom/memory/dataset.rb +2 -0
- data/lib/rom/memory/gateway.rb +2 -0
- data/lib/rom/memory/mapper_compiler.rb +2 -0
- data/lib/rom/memory/relation.rb +2 -0
- data/lib/rom/memory/schema.rb +2 -0
- data/lib/rom/memory/storage.rb +2 -0
- data/lib/rom/memory/types.rb +2 -0
- data/lib/rom/model_builder.rb +103 -0
- data/lib/rom/open_struct.rb +37 -0
- data/lib/rom/pipeline.rb +2 -0
- data/lib/rom/plugin.rb +2 -0
- data/lib/rom/plugin_base.rb +2 -0
- data/lib/rom/plugin_registry.rb +2 -0
- data/lib/rom/plugins/command/schema.rb +2 -0
- data/lib/rom/plugins/command/timestamps.rb +2 -0
- data/lib/rom/plugins/relation/instrumentation.rb +2 -0
- data/lib/rom/plugins/relation/registry_reader.rb +2 -0
- data/lib/rom/plugins/schema/timestamps.rb +8 -1
- data/lib/rom/processor.rb +30 -0
- data/lib/rom/processor/transproc.rb +417 -0
- data/lib/rom/registry.rb +2 -0
- data/lib/rom/relation.rb +4 -2
- data/lib/rom/relation/class_interface.rb +2 -0
- data/lib/rom/relation/combined.rb +2 -0
- data/lib/rom/relation/commands.rb +2 -0
- data/lib/rom/relation/composite.rb +2 -0
- data/lib/rom/relation/curried.rb +3 -1
- data/lib/rom/relation/graph.rb +2 -0
- data/lib/rom/relation/loaded.rb +2 -0
- data/lib/rom/relation/materializable.rb +2 -0
- data/lib/rom/relation/name.rb +2 -0
- data/lib/rom/relation/view_dsl.rb +2 -0
- data/lib/rom/relation/wrap.rb +2 -0
- data/lib/rom/relation_registry.rb +2 -0
- data/lib/rom/schema.rb +39 -6
- data/lib/rom/schema/associations_dsl.rb +5 -3
- data/lib/rom/schema/dsl.rb +41 -11
- data/lib/rom/schema/inferrer.rb +21 -3
- data/lib/rom/schema_plugin.rb +2 -0
- data/lib/rom/setup.rb +2 -0
- data/lib/rom/setup/auto_registration.rb +2 -0
- data/lib/rom/setup/auto_registration_strategies/base.rb +3 -1
- data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +2 -0
- data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +2 -0
- data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +2 -0
- data/lib/rom/setup/finalize.rb +2 -0
- data/lib/rom/setup/finalize/finalize_commands.rb +2 -0
- data/lib/rom/setup/finalize/finalize_mappers.rb +2 -0
- data/lib/rom/setup/finalize/finalize_relations.rb +2 -0
- data/lib/rom/struct.rb +108 -0
- data/lib/rom/struct_compiler.rb +110 -0
- data/lib/rom/support/configurable.rb +2 -0
- data/lib/rom/support/inflector.rb +2 -0
- data/lib/rom/support/memoizable.rb +2 -0
- data/lib/rom/support/notifications.rb +2 -0
- data/lib/rom/transaction.rb +2 -0
- data/lib/rom/transformer.rb +34 -0
- data/lib/rom/types.rb +10 -3
- data/lib/rom/version.rb +3 -1
- metadata +37 -21
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/core/class_builder'
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
class Mapper
|
7
|
+
# Setup DSL-specific mapper extensions
|
8
|
+
#
|
9
|
+
# @private
|
10
|
+
class Builder
|
11
|
+
# Generate a mapper subclass
|
12
|
+
#
|
13
|
+
# This is used by Setup#mappers DSL
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
def self.build_class(name, mapper_registry, options = EMPTY_HASH, &block)
|
17
|
+
class_name = "ROM::Mapper[#{name}]"
|
18
|
+
|
19
|
+
parent = options[:parent]
|
20
|
+
inherit_header = options.fetch(:inherit_header) { ROM::Mapper.inherit_header }
|
21
|
+
|
22
|
+
parent_class =
|
23
|
+
if parent
|
24
|
+
mapper_registry.detect { |klass| klass.relation == parent }
|
25
|
+
else
|
26
|
+
ROM::Mapper
|
27
|
+
end
|
28
|
+
|
29
|
+
Dry::Core::ClassBuilder.new(name: class_name, parent: parent_class).call do |klass|
|
30
|
+
klass.register_as(name)
|
31
|
+
klass.relation(name)
|
32
|
+
klass.inherit_header(inherit_header)
|
33
|
+
|
34
|
+
klass.class_eval(&block) if block
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rom/mapper/mapper_dsl'
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
class Mapper
|
7
|
+
# Model DSL allows setting a model class
|
8
|
+
#
|
9
|
+
# @private
|
10
|
+
module ConfigurationPlugin
|
11
|
+
# Mapper definition DSL used by Setup DSL
|
12
|
+
#
|
13
|
+
# @private
|
14
|
+
|
15
|
+
def self.apply(configuration, options = {})
|
16
|
+
configuration.extend Methods
|
17
|
+
configuration
|
18
|
+
end
|
19
|
+
|
20
|
+
module Methods
|
21
|
+
def mappers(&block)
|
22
|
+
register_mapper(*MapperDSL.new(self, mapper_classes, block).mapper_classes)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/core/class_attributes'
|
4
|
+
require 'rom/mapper/attribute_dsl'
|
5
|
+
|
6
|
+
module ROM
|
7
|
+
class Mapper
|
8
|
+
# Mapper class-level DSL including Attribute DSL and Model DSL
|
9
|
+
module DSL
|
10
|
+
# Extend mapper class with macros and DSL methods
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
def self.included(klass)
|
14
|
+
klass.extend(Dry::Core::ClassAttributes)
|
15
|
+
klass.extend(ClassMethods)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Class methods for all mappers
|
19
|
+
#
|
20
|
+
# @private
|
21
|
+
module ClassMethods
|
22
|
+
# Set base ivars for the mapper class
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
def inherited(klass)
|
26
|
+
super
|
27
|
+
|
28
|
+
klass.instance_variable_set('@attributes', nil)
|
29
|
+
klass.instance_variable_set('@header', nil)
|
30
|
+
klass.instance_variable_set('@dsl', nil)
|
31
|
+
end
|
32
|
+
|
33
|
+
# include a registered plugin in this mapper
|
34
|
+
#
|
35
|
+
# @param [Symbol] plugin
|
36
|
+
# @param [Hash] options
|
37
|
+
# @option options [Symbol] :adapter (:default) first adapter to check for plugin
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
def use(plugin, options = {})
|
41
|
+
adapter = options.fetch(:adapter, :default)
|
42
|
+
|
43
|
+
ROM.plugin_registry.mappers.fetch(plugin, adapter).apply_to(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Return base_relation used for creating mapper registry
|
47
|
+
#
|
48
|
+
# This is used to "gather" mappers under same root name
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
def base_relation
|
52
|
+
if superclass.relation
|
53
|
+
superclass.relation
|
54
|
+
else
|
55
|
+
relation
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Return header of the mapper
|
60
|
+
#
|
61
|
+
# This is memoized so mutating mapper class won't have an effect wrt
|
62
|
+
# header after it was initialized for the first time.
|
63
|
+
#
|
64
|
+
# TODO: freezing mapper class here is probably a good idea
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
def header
|
68
|
+
@header ||= dsl.header
|
69
|
+
end
|
70
|
+
|
71
|
+
# @api private
|
72
|
+
def respond_to_missing?(name, _include_private = false)
|
73
|
+
dsl.respond_to?(name) || super
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
# Return default Attribute DSL options based on settings of the mapper
|
79
|
+
# class
|
80
|
+
#
|
81
|
+
# @api private
|
82
|
+
def options
|
83
|
+
{ copy_keys: copy_keys,
|
84
|
+
prefix: prefix,
|
85
|
+
prefix_separator: prefix_separator,
|
86
|
+
symbolize_keys: symbolize_keys,
|
87
|
+
reject_keys: reject_keys }
|
88
|
+
end
|
89
|
+
|
90
|
+
# Return default attributes that might have been inherited from the
|
91
|
+
# superclass
|
92
|
+
#
|
93
|
+
# @api private
|
94
|
+
def attributes
|
95
|
+
@attributes ||=
|
96
|
+
if superclass.respond_to?(:attributes, true) && inherit_header
|
97
|
+
superclass.attributes.dup
|
98
|
+
else
|
99
|
+
[]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Create the attribute DSL instance used by the mapper class
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
def dsl
|
107
|
+
@dsl ||= AttributeDSL.new(attributes, options)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Delegate Attribute DSL method to the dsl instance
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
def method_missing(name, *args, &block)
|
114
|
+
if dsl.respond_to?(name)
|
115
|
+
dsl.public_send(name, *args, &block)
|
116
|
+
else
|
117
|
+
super
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rom/mapper/builder'
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
class Mapper
|
7
|
+
# Mapper definition DSL used by Setup DSL
|
8
|
+
#
|
9
|
+
# @private
|
10
|
+
class MapperDSL
|
11
|
+
attr_reader :configuration, :mapper_classes, :defined_mappers
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
def initialize(configuration, mapper_classes, block)
|
15
|
+
@configuration = configuration
|
16
|
+
@mapper_classes = mapper_classes
|
17
|
+
@defined_mappers = []
|
18
|
+
|
19
|
+
instance_exec(&block)
|
20
|
+
|
21
|
+
@mapper_classes = @defined_mappers
|
22
|
+
end
|
23
|
+
|
24
|
+
# Define a mapper class
|
25
|
+
#
|
26
|
+
# @param [Symbol] name of the mapper
|
27
|
+
# @param [Hash] options
|
28
|
+
#
|
29
|
+
# @return [Class]
|
30
|
+
#
|
31
|
+
# @api public
|
32
|
+
def define(name, options = EMPTY_HASH, &block)
|
33
|
+
@defined_mappers << Builder.build_class(name, (@mapper_classes + @defined_mappers), options, &block)
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
# TODO
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
def register(relation, mappers)
|
41
|
+
configuration.register_mapper(relation => mappers)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rom/model_builder'
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
class Mapper
|
7
|
+
# Model DSL allows setting a model class
|
8
|
+
#
|
9
|
+
# @private
|
10
|
+
module ModelDSL
|
11
|
+
attr_reader :attributes, :builder, :klass
|
12
|
+
|
13
|
+
DEFAULT_TYPE = :poro
|
14
|
+
|
15
|
+
# Set or generate a model
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# class MyDefinition
|
19
|
+
# include ROM::Mapper::ModelDSL
|
20
|
+
#
|
21
|
+
# def initialize
|
22
|
+
# @attributes = [[:name], [:title]]
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# definition = MyDefinition.new
|
27
|
+
#
|
28
|
+
# # just set a model constant
|
29
|
+
# definition.model(User)
|
30
|
+
#
|
31
|
+
# # generate model class for the attributes
|
32
|
+
# definition.model(name: 'User')
|
33
|
+
#
|
34
|
+
# @api public
|
35
|
+
def model(options = nil)
|
36
|
+
if options.is_a?(Class)
|
37
|
+
@klass = options
|
38
|
+
elsif options
|
39
|
+
type = options.fetch(:type) { DEFAULT_TYPE }
|
40
|
+
@builder = ModelBuilder[type].new(options)
|
41
|
+
end
|
42
|
+
|
43
|
+
build_class unless options
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Build a model class using a specialized builder
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
def build_class
|
52
|
+
return klass if klass
|
53
|
+
included_attrs = attributes.reject do |_name, opts|
|
54
|
+
opts && opts[:exclude]
|
55
|
+
end
|
56
|
+
builder.call(included_attrs.map(&:first)) if builder
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/core/class_attributes'
|
4
|
+
|
5
|
+
require 'rom/constants'
|
6
|
+
require 'rom/initializer'
|
7
|
+
require 'rom/mapper'
|
8
|
+
require 'rom/struct'
|
9
|
+
require 'rom/struct_compiler'
|
10
|
+
require 'rom/cache'
|
11
|
+
|
12
|
+
module ROM
|
13
|
+
# @api private
|
14
|
+
class MapperCompiler
|
15
|
+
extend Dry::Core::ClassAttributes
|
16
|
+
extend Initializer
|
17
|
+
|
18
|
+
defines :mapper_options
|
19
|
+
|
20
|
+
mapper_options(EMPTY_HASH)
|
21
|
+
|
22
|
+
option :cache, default: -> { Cache.new }
|
23
|
+
|
24
|
+
attr_reader :struct_compiler
|
25
|
+
|
26
|
+
attr_reader :mapper_options
|
27
|
+
|
28
|
+
def initialize(*args)
|
29
|
+
super
|
30
|
+
@struct_compiler = StructCompiler.new(cache: cache)
|
31
|
+
@cache = cache.namespaced(:mappers)
|
32
|
+
@mapper_options = self.class.mapper_options
|
33
|
+
end
|
34
|
+
|
35
|
+
def call(ast)
|
36
|
+
cache.fetch_or_store(ast.hash) { Mapper.build(Header.coerce(*visit(ast))) }
|
37
|
+
end
|
38
|
+
alias_method :[], :call
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def visit(node)
|
43
|
+
name, node = node
|
44
|
+
__send__("visit_#{name}", node)
|
45
|
+
end
|
46
|
+
|
47
|
+
def visit_relation(node)
|
48
|
+
rel_name, header, meta_options = node
|
49
|
+
name = meta_options[:combine_name] || meta_options[:alias] || rel_name
|
50
|
+
namespace = meta_options.fetch(:struct_namespace)
|
51
|
+
|
52
|
+
model = meta_options.fetch(:model) do
|
53
|
+
if meta_options[:combine_name]
|
54
|
+
false
|
55
|
+
else
|
56
|
+
struct_compiler[name, header, namespace]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
options = [header.map(&method(:visit)), mapper_options.merge(model: model)]
|
61
|
+
|
62
|
+
if meta_options[:combine_type]
|
63
|
+
type = meta_options[:combine_type] == :many ? :array : :hash
|
64
|
+
keys = meta_options.fetch(:keys)
|
65
|
+
|
66
|
+
[name, combine: true, type: type, keys: keys, header: Header.coerce(*options)]
|
67
|
+
elsif meta_options[:wrap]
|
68
|
+
[name, wrap: true, type: :hash, header: Header.coerce(*options)]
|
69
|
+
else
|
70
|
+
options
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def visit_attribute(node)
|
75
|
+
name, _, meta_options = node
|
76
|
+
|
77
|
+
if meta_options[:alias]
|
78
|
+
[meta_options[:alias], from: name]
|
79
|
+
else
|
80
|
+
[name]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/rom/mapper_registry.rb
CHANGED
data/lib/rom/memory.rb
CHANGED
data/lib/rom/memory/commands.rb
CHANGED