rom-core 5.1.2 → 5.2.1
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/lib/rom/array_dataset.rb +4 -4
- data/lib/rom/association_set.rb +2 -3
- data/lib/rom/associations/definitions/abstract.rb +2 -2
- data/lib/rom/associations/many_to_many.rb +1 -0
- data/lib/rom/attribute.rb +5 -4
- data/lib/rom/auto_curry.rb +2 -0
- data/lib/rom/command.rb +6 -6
- data/lib/rom/command_compiler.rb +5 -7
- data/lib/rom/commands/class_interface.rb +7 -7
- data/lib/rom/commands/composite.rb +1 -1
- data/lib/rom/commands/graph/input_evaluator.rb +1 -1
- data/lib/rom/commands/lazy.rb +2 -1
- data/lib/rom/commands/lazy/create.rb +1 -1
- data/lib/rom/commands/lazy/update.rb +3 -3
- data/lib/rom/configuration.rb +5 -5
- data/lib/rom/configuration_dsl/relation.rb +1 -1
- data/lib/rom/constants.rb +1 -1
- data/lib/rom/core/version.rb +1 -1
- data/lib/rom/data_proxy.rb +3 -2
- data/lib/rom/enumerable_dataset.rb +4 -4
- data/lib/rom/environment.rb +0 -1
- data/lib/rom/header/attribute.rb +2 -4
- data/lib/rom/initializer.rb +9 -7
- data/lib/rom/lint/gateway.rb +1 -3
- data/lib/rom/lint/linter.rb +3 -4
- data/lib/rom/lint/spec.rb +2 -2
- data/lib/rom/mapper.rb +4 -3
- data/lib/rom/mapper/attribute_dsl.rb +5 -5
- data/lib/rom/mapper/dsl.rb +2 -5
- data/lib/rom/mapper/model_dsl.rb +2 -1
- data/lib/rom/mapper_compiler.rb +2 -1
- data/lib/rom/mapper_registry.rb +3 -3
- data/lib/rom/memory/dataset.rb +4 -3
- data/lib/rom/pipeline.rb +3 -1
- data/lib/rom/plugin.rb +3 -3
- data/lib/rom/plugin_registry.rb +1 -1
- data/lib/rom/plugins/command/schema.rb +2 -2
- data/lib/rom/plugins/relation/instrumentation.rb +1 -1
- data/lib/rom/plugins/relation/registry_reader.rb +4 -3
- data/lib/rom/plugins/schema/timestamps.rb +4 -6
- data/lib/rom/processor.rb +1 -1
- data/lib/rom/processor/transproc.rb +16 -19
- data/lib/rom/registry.rb +17 -12
- data/lib/rom/relation.rb +6 -6
- data/lib/rom/relation/class_interface.rb +9 -8
- data/lib/rom/relation/curried.rb +3 -2
- data/lib/rom/relation/loaded.rb +1 -0
- data/lib/rom/relation/materializable.rb +1 -0
- data/lib/rom/relation/name.rb +1 -1
- data/lib/rom/relation_registry.rb +1 -1
- data/lib/rom/schema.rb +22 -22
- data/lib/rom/schema/associations_dsl.rb +17 -17
- data/lib/rom/schema/dsl.rb +6 -6
- data/lib/rom/schema/inferrer.rb +2 -4
- data/lib/rom/setup.rb +2 -2
- data/lib/rom/setup/auto_registration.rb +1 -1
- data/lib/rom/setup/auto_registration_strategies/base.rb +1 -1
- data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +4 -4
- data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +1 -1
- data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +1 -1
- data/lib/rom/setup/finalize/finalize_commands.rb +7 -4
- data/lib/rom/setup/finalize/finalize_mappers.rb +9 -8
- data/lib/rom/setup/finalize/finalize_relations.rb +2 -2
- data/lib/rom/struct.rb +1 -1
- data/lib/rom/struct_compiler.rb +6 -5
- data/lib/rom/support/memoizable.rb +3 -2
- data/lib/rom/transaction.rb +1 -1
- data/lib/rom/transformer.rb +1 -0
- metadata +3 -3
data/lib/rom/initializer.rb
CHANGED
@@ -11,6 +11,7 @@ module ROM
|
|
11
11
|
def param(*)
|
12
12
|
super.tap { __define_with__ }
|
13
13
|
end
|
14
|
+
ruby2_keywords(:param) if respond_to?(:ruby2_keywords, true)
|
14
15
|
|
15
16
|
# @api private
|
16
17
|
def option(*)
|
@@ -18,25 +19,26 @@ module ROM
|
|
18
19
|
__define_with__ unless method_defined?(:with)
|
19
20
|
end
|
20
21
|
end
|
22
|
+
ruby2_keywords(:option) if respond_to?(:ruby2_keywords, true)
|
21
23
|
|
22
24
|
# @api private
|
23
25
|
def __define_with__
|
24
|
-
seq_names = dry_initializer
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
seq_names = dry_initializer
|
27
|
+
.definitions
|
28
|
+
.reject { |_, d| d.option }
|
29
|
+
.keys
|
30
|
+
.join(', ')
|
29
31
|
|
30
32
|
seq_names << ', ' unless seq_names.empty?
|
31
33
|
|
32
34
|
undef_method(:with) if method_defined?(:with)
|
33
35
|
|
34
36
|
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
35
|
-
def with(new_options
|
37
|
+
def with(**new_options)
|
36
38
|
if new_options.empty?
|
37
39
|
self
|
38
40
|
else
|
39
|
-
self.class.new(#{
|
41
|
+
self.class.new(#{seq_names}**options, **new_options)
|
40
42
|
end
|
41
43
|
end
|
42
44
|
RUBY
|
data/lib/rom/lint/gateway.rb
CHANGED
@@ -77,9 +77,7 @@ module ROM
|
|
77
77
|
def lint_transaction_support
|
78
78
|
result = gateway_instance.transaction { 1 }
|
79
79
|
|
80
|
-
if result != 1
|
81
|
-
complain "#{gateway_instance} must return the result of a transaction block"
|
82
|
-
end
|
80
|
+
complain "#{gateway_instance} must return the result of a transaction block" if result != 1
|
83
81
|
|
84
82
|
gateway_instance.transaction do |t|
|
85
83
|
t.rollback!
|
data/lib/rom/lint/linter.rb
CHANGED
@@ -27,6 +27,7 @@ module ROM
|
|
27
27
|
# @api public
|
28
28
|
def self.each_lint
|
29
29
|
return to_enum unless block_given?
|
30
|
+
|
30
31
|
lints.each { |lint| yield lint, self }
|
31
32
|
end
|
32
33
|
|
@@ -67,14 +68,12 @@ module ROM
|
|
67
68
|
# Hook method executed before each lint method run
|
68
69
|
#
|
69
70
|
# @api private
|
70
|
-
def before_lint
|
71
|
-
end
|
71
|
+
def before_lint; end
|
72
72
|
|
73
73
|
# Hook method executed after each lint method run
|
74
74
|
#
|
75
75
|
# @api private
|
76
|
-
def after_lint
|
77
|
-
end
|
76
|
+
def after_lint; end
|
78
77
|
end
|
79
78
|
end
|
80
79
|
end
|
data/lib/rom/lint/spec.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'rom/lint/gateway'
|
4
4
|
require 'rom/lint/enumerable_dataset'
|
5
5
|
|
6
|
-
RSpec.shared_examples
|
6
|
+
RSpec.shared_examples 'a rom gateway' do
|
7
7
|
ROM::Lint::Gateway.each_lint do |name, linter|
|
8
8
|
it name do
|
9
9
|
result = linter.new(identifier, gateway, uri).lint(name)
|
@@ -12,7 +12,7 @@ RSpec.shared_examples "a rom gateway" do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
RSpec.shared_examples
|
15
|
+
RSpec.shared_examples 'a rom enumerable dataset' do
|
16
16
|
ROM::Lint::EnumerableDataset.each_lint do |name, linter|
|
17
17
|
it name do
|
18
18
|
result = linter.new(dataset, data).lint(name)
|
data/lib/rom/mapper.rb
CHANGED
@@ -12,11 +12,11 @@ module ROM
|
|
12
12
|
include Dry::Equalizer(:transformers, :header)
|
13
13
|
|
14
14
|
defines :relation, :register_as, :symbolize_keys, :copy_keys,
|
15
|
-
|
15
|
+
:prefix, :prefix_separator, :inherit_header, :reject_keys
|
16
16
|
|
17
17
|
inherit_header true
|
18
18
|
reject_keys false
|
19
|
-
prefix_separator '_'
|
19
|
+
prefix_separator '_'
|
20
20
|
|
21
21
|
# @return [Object] transformers object built by a processor
|
22
22
|
#
|
@@ -53,7 +53,8 @@ module ROM
|
|
53
53
|
def self.headers(header)
|
54
54
|
return [header] if steps.empty?
|
55
55
|
return steps.map(&:header) if attributes.empty?
|
56
|
-
|
56
|
+
|
57
|
+
raise(MapperMisconfiguredError, 'cannot mix outer attributes and steps')
|
57
58
|
end
|
58
59
|
|
59
60
|
# Build a mapper using provided processor type
|
@@ -78,8 +78,10 @@ module ROM
|
|
78
78
|
# @api public
|
79
79
|
def attribute(name, options = EMPTY_HASH, &block)
|
80
80
|
with_attr_options(name, options) do |attr_options|
|
81
|
-
|
82
|
-
|
81
|
+
if options[:type] && block
|
82
|
+
raise ArgumentError,
|
83
|
+
"can't specify type and block at the same time"
|
84
|
+
end
|
83
85
|
attr_options[:coercer] = block if block
|
84
86
|
add_attribute(name, attr_options)
|
85
87
|
end
|
@@ -370,9 +372,7 @@ module ROM
|
|
370
372
|
attr_options[:from] = attr_options[:from].to_sym if name.is_a? Symbol
|
371
373
|
end
|
372
374
|
|
373
|
-
if symbolize_keys
|
374
|
-
attr_options.update(from: attr_options.fetch(:from) { name }.to_s)
|
375
|
-
end
|
375
|
+
attr_options.update(from: attr_options.fetch(:from) { name }.to_s) if symbolize_keys
|
376
376
|
|
377
377
|
yield(attr_options)
|
378
378
|
end
|
data/lib/rom/mapper/dsl.rb
CHANGED
@@ -49,11 +49,7 @@ module ROM
|
|
49
49
|
#
|
50
50
|
# @api private
|
51
51
|
def base_relation
|
52
|
-
|
53
|
-
superclass.relation
|
54
|
-
else
|
55
|
-
relation
|
56
|
-
end
|
52
|
+
superclass.relation || relation
|
57
53
|
end
|
58
54
|
|
59
55
|
# Return header of the mapper
|
@@ -117,6 +113,7 @@ module ROM
|
|
117
113
|
super
|
118
114
|
end
|
119
115
|
end
|
116
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
120
117
|
end
|
121
118
|
end
|
122
119
|
end
|
data/lib/rom/mapper/model_dsl.rb
CHANGED
@@ -50,10 +50,11 @@ module ROM
|
|
50
50
|
# @api private
|
51
51
|
def build_class
|
52
52
|
return klass if klass
|
53
|
+
|
53
54
|
included_attrs = attributes.reject do |_name, opts|
|
54
55
|
opts && opts[:exclude]
|
55
56
|
end
|
56
|
-
builder
|
57
|
+
builder&.call(included_attrs.map(&:first))
|
57
58
|
end
|
58
59
|
end
|
59
60
|
end
|
data/lib/rom/mapper_compiler.rb
CHANGED
@@ -25,12 +25,13 @@ module ROM
|
|
25
25
|
|
26
26
|
attr_reader :mapper_options
|
27
27
|
|
28
|
-
def initialize(*
|
28
|
+
def initialize(*)
|
29
29
|
super
|
30
30
|
@struct_compiler = StructCompiler.new(cache: cache)
|
31
31
|
@cache = cache.namespaced(:mappers)
|
32
32
|
@mapper_options = self.class.mapper_options
|
33
33
|
end
|
34
|
+
ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
|
34
35
|
|
35
36
|
def call(ast)
|
36
37
|
cache.fetch_or_store(ast.hash) { Mapper.build(Header.coerce(*visit(ast))) }
|
data/lib/rom/mapper_registry.rb
CHANGED
@@ -14,9 +14,9 @@ module ROM
|
|
14
14
|
|
15
15
|
# @!attribute [r] compiler
|
16
16
|
# @return [MapperCompiler] A mapper compiler instance
|
17
|
-
option :compiler, default:
|
18
|
-
MapperCompiler.new(cache: cache)
|
19
|
-
|
17
|
+
option :compiler, default: lambda {
|
18
|
+
MapperCompiler.new(EMPTY_HASH, cache: cache)
|
19
|
+
}
|
20
20
|
|
21
21
|
# @see Registry
|
22
22
|
# @api public
|
data/lib/rom/memory/dataset.rb
CHANGED
@@ -31,7 +31,7 @@ module ROM
|
|
31
31
|
join_map[tuple].map { |other| tuple.merge(other) }
|
32
32
|
}
|
33
33
|
|
34
|
-
self.class.new(tuples, options)
|
34
|
+
self.class.new(tuples, **options)
|
35
35
|
end
|
36
36
|
|
37
37
|
# Restrict a dataset
|
@@ -63,7 +63,7 @@ module ROM
|
|
63
63
|
#
|
64
64
|
# @api public
|
65
65
|
def project(*names)
|
66
|
-
map { |tuple| tuple.
|
66
|
+
map { |tuple| tuple.select { |key| names.include?(key) } }
|
67
67
|
end
|
68
68
|
|
69
69
|
# Sort a dataset
|
@@ -119,7 +119,8 @@ module ROM
|
|
119
119
|
# @api private
|
120
120
|
def __compare__(a, b, nils_first)
|
121
121
|
return a <=> b unless a.nil? ^ b.nil?
|
122
|
-
|
122
|
+
|
123
|
+
nils_first ^ b.nil? ? -1 : 1
|
123
124
|
end
|
124
125
|
end
|
125
126
|
end
|
data/lib/rom/pipeline.rb
CHANGED
@@ -75,13 +75,15 @@ module ROM
|
|
75
75
|
super
|
76
76
|
end
|
77
77
|
end
|
78
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
78
79
|
end
|
79
80
|
|
80
81
|
# Base composite class with left-to-right pipeline behavior
|
81
82
|
#
|
82
83
|
# @api private
|
83
84
|
class Composite
|
84
|
-
(Kernel.private_instance_methods - %i
|
85
|
+
(Kernel.private_instance_methods - %i[respond_to_missing? block_given?])
|
86
|
+
.each(&method(:undef_method))
|
85
87
|
|
86
88
|
include Dry::Equalizer(:left, :right)
|
87
89
|
include Proxy
|
data/lib/rom/plugin.rb
CHANGED
@@ -32,11 +32,11 @@ module ROM
|
|
32
32
|
# @param [Class,Object] target
|
33
33
|
#
|
34
34
|
# @api private
|
35
|
-
def apply_to(target, options
|
35
|
+
def apply_to(target, **options)
|
36
36
|
if mod.respond_to?(:apply)
|
37
|
-
mod.apply(target, options)
|
37
|
+
mod.apply(target, **options)
|
38
38
|
elsif mod.respond_to?(:new)
|
39
|
-
target.include(mod.new(options))
|
39
|
+
target.include(mod.new(**options))
|
40
40
|
elsif target.is_a?(::Module)
|
41
41
|
target.include(mod)
|
42
42
|
end
|
data/lib/rom/plugin_registry.rb
CHANGED
@@ -21,7 +21,7 @@ module ROM
|
|
21
21
|
# @return [Command]
|
22
22
|
#
|
23
23
|
# @api public
|
24
|
-
def build(relation, options
|
24
|
+
def build(relation, **options)
|
25
25
|
if options.key?(:input) || !relation.schema?
|
26
26
|
super
|
27
27
|
else
|
@@ -34,7 +34,7 @@ module ROM
|
|
34
34
|
relation.input_schema
|
35
35
|
end
|
36
36
|
|
37
|
-
super(relation, options
|
37
|
+
super(relation, **options, input: input_handler)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -10,14 +10,14 @@ module ROM
|
|
10
10
|
# For now this plugin is always enabled
|
11
11
|
#
|
12
12
|
# @api public
|
13
|
-
class RegistryReader < Module
|
14
|
-
EMPTY_REGISTRY = RelationRegistry.
|
13
|
+
class RegistryReader < ::Module
|
14
|
+
EMPTY_REGISTRY = RelationRegistry.build(EMPTY_HASH).freeze
|
15
15
|
|
16
16
|
# @api private
|
17
17
|
attr_reader :relations
|
18
18
|
|
19
19
|
# @api private
|
20
|
-
def initialize(relations)
|
20
|
+
def initialize(relations:)
|
21
21
|
@relations = relations
|
22
22
|
define_readers!
|
23
23
|
end
|
@@ -26,6 +26,7 @@ module ROM
|
|
26
26
|
def included(klass)
|
27
27
|
super
|
28
28
|
return if klass.instance_methods.include?(:__registry__)
|
29
|
+
|
29
30
|
klass.option :__registry__, default: -> { EMPTY_REGISTRY }
|
30
31
|
end
|
31
32
|
|
@@ -23,13 +23,11 @@ module ROM
|
|
23
23
|
#
|
24
24
|
# @api public
|
25
25
|
module Timestamps
|
26
|
-
DEFAULT_TIMESTAMPS = %i
|
26
|
+
DEFAULT_TIMESTAMPS = %i[created_at updated_at].freeze
|
27
27
|
|
28
28
|
# @api private
|
29
|
-
def self.apply(schema,
|
30
|
-
|
31
|
-
names = options.fetch(:attributes, DEFAULT_TIMESTAMPS)
|
32
|
-
attributes = names.map do |name|
|
29
|
+
def self.apply(schema, type: Types::Time, attributes: DEFAULT_TIMESTAMPS)
|
30
|
+
attrs = attributes.map do |name|
|
33
31
|
ROM::Schema.build_attribute_info(
|
34
32
|
type.meta(source: schema.name),
|
35
33
|
name: name
|
@@ -37,7 +35,7 @@ module ROM
|
|
37
35
|
end
|
38
36
|
|
39
37
|
schema.attributes.concat(
|
40
|
-
schema.class.attributes(
|
38
|
+
schema.class.attributes(attrs, schema.attr_class)
|
41
39
|
)
|
42
40
|
end
|
43
41
|
|
data/lib/rom/processor.rb
CHANGED
@@ -24,11 +24,8 @@ module ROM
|
|
24
24
|
import ::Transproc::HashTransformations
|
25
25
|
import ::Transproc::ClassTransformations
|
26
26
|
import ::Transproc::ProcTransformations
|
27
|
-
INVALID_INJECT_UNION_VALUE = "%s attribute: block is required for :from with union value.".freeze
|
28
27
|
|
29
|
-
|
30
|
-
tuple
|
31
|
-
end
|
28
|
+
INVALID_INJECT_UNION_VALUE = '%s attribute: block is required for :from with union value.'
|
32
29
|
|
33
30
|
def self.get(arr, idx)
|
34
31
|
arr[idx]
|
@@ -39,7 +36,7 @@ module ROM
|
|
39
36
|
end
|
40
37
|
|
41
38
|
def self.inject_union_value(tuple, name, keys, coercer)
|
42
|
-
raise ROM::MapperMisconfiguredError, INVALID_INJECT_UNION_VALUE % [name]
|
39
|
+
raise ROM::MapperMisconfiguredError, INVALID_INJECT_UNION_VALUE % [name] unless coercer
|
43
40
|
|
44
41
|
values = tuple.values_at(*keys)
|
45
42
|
result = coercer.call(*values)
|
@@ -315,22 +312,22 @@ module ROM
|
|
315
312
|
#
|
316
313
|
# @api private
|
317
314
|
def visit_unfold(attribute, preprocess = false)
|
318
|
-
|
319
|
-
name = attribute.name
|
320
|
-
header = attribute.header
|
321
|
-
keys = attribute.pop_keys
|
322
|
-
key = keys.first
|
315
|
+
return unless preprocess
|
323
316
|
|
324
|
-
|
317
|
+
name = attribute.name
|
318
|
+
header = attribute.header
|
319
|
+
keys = attribute.pop_keys
|
320
|
+
key = keys.first
|
325
321
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
322
|
+
others = header.postprocessed
|
323
|
+
|
324
|
+
compose do |ops|
|
325
|
+
ops << others.map { |attr|
|
326
|
+
t(:map_array, t(:map_value, name, visit(attr, true)))
|
327
|
+
}
|
328
|
+
ops << t(:map_array, t(:map_value, name, t(:insert_key, key)))
|
329
|
+
ops << t(:map_array, t(:reject_keys, [key] - [name]))
|
330
|
+
ops << t(:ungroup, name, [key])
|
334
331
|
end
|
335
332
|
end
|
336
333
|
|
data/lib/rom/registry.rb
CHANGED
@@ -26,21 +26,25 @@ module ROM
|
|
26
26
|
option :cache, default: -> { Cache.new }
|
27
27
|
|
28
28
|
# @api private
|
29
|
-
def self.new(*args)
|
30
|
-
|
31
|
-
|
32
|
-
super({}, {})
|
33
|
-
when 1
|
34
|
-
super(*args, {})
|
29
|
+
def self.new(*args, **kwargs)
|
30
|
+
if args.empty? && kwargs.empty?
|
31
|
+
super({}, **{})
|
35
32
|
else
|
36
|
-
super
|
33
|
+
super
|
37
34
|
end
|
38
35
|
end
|
39
36
|
|
37
|
+
# Create a registry without options
|
38
|
+
#
|
39
|
+
# @api private
|
40
|
+
def self.build(elements = {})
|
41
|
+
new(elements, **{})
|
42
|
+
end
|
43
|
+
|
40
44
|
# @api private
|
41
45
|
def self.[](identifier)
|
42
46
|
fetch_or_store(identifier) do
|
43
|
-
Dry::Core::ClassBuilder
|
47
|
+
::Dry::Core::ClassBuilder
|
44
48
|
.new(parent: self, name: "#{name}[:#{identifier}]")
|
45
49
|
.call
|
46
50
|
end
|
@@ -53,7 +57,7 @@ module ROM
|
|
53
57
|
|
54
58
|
# @api private
|
55
59
|
def merge(other)
|
56
|
-
self.class.new(Hash(other), options)
|
60
|
+
self.class.new(Hash(other), **options)
|
57
61
|
end
|
58
62
|
|
59
63
|
# @api private
|
@@ -62,16 +66,17 @@ module ROM
|
|
62
66
|
end
|
63
67
|
|
64
68
|
# @api private
|
65
|
-
def map
|
69
|
+
def map
|
66
70
|
new_elements = elements.each_with_object({}) do |(name, element), h|
|
67
71
|
h[name] = yield(element)
|
68
72
|
end
|
69
|
-
self.class.new(new_elements, options)
|
73
|
+
self.class.new(new_elements, **options)
|
70
74
|
end
|
71
75
|
|
72
76
|
# @api private
|
73
77
|
def each
|
74
78
|
return to_enum unless block_given?
|
79
|
+
|
75
80
|
elements.each { |element| yield(element) }
|
76
81
|
end
|
77
82
|
|
@@ -82,7 +87,7 @@ module ROM
|
|
82
87
|
|
83
88
|
# @api private
|
84
89
|
def fetch(key)
|
85
|
-
raise ArgumentError
|
90
|
+
raise ArgumentError, 'key cannot be nil' if key.nil?
|
86
91
|
|
87
92
|
elements.fetch(key.to_sym) do
|
88
93
|
return yield if block_given?
|