rom-core 4.2.1 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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