rom-core 4.0.0.beta3 → 4.0.0.rc1
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 +3 -1
- data/lib/rom/association_set.rb +3 -0
- data/lib/rom/associations/abstract.rb +72 -1
- data/lib/rom/associations/definitions/abstract.rb +22 -6
- data/lib/rom/associations/definitions/many_to_many.rb +3 -0
- data/lib/rom/associations/definitions/many_to_one.rb +1 -0
- data/lib/rom/associations/definitions/one_to_many.rb +1 -0
- data/lib/rom/associations/definitions/one_to_one.rb +1 -0
- data/lib/rom/associations/definitions/one_to_one_through.rb +1 -0
- data/lib/rom/associations/many_to_many.rb +44 -0
- data/lib/rom/associations/many_to_one.rb +26 -0
- data/lib/rom/associations/one_to_many.rb +26 -0
- data/lib/rom/associations/one_to_one.rb +3 -0
- data/lib/rom/associations/one_to_one_through.rb +3 -0
- data/lib/rom/attribute.rb +2 -2
- data/lib/rom/auto_curry.rb +11 -0
- data/lib/rom/cache.rb +29 -0
- data/lib/rom/command_compiler.rb +4 -4
- data/lib/rom/command_registry.rb +9 -5
- data/lib/rom/commands/class_interface.rb +7 -7
- data/lib/rom/commands/graph/input_evaluator.rb +33 -3
- data/lib/rom/commands/lazy.rb +4 -0
- data/lib/rom/commands/lazy/create.rb +10 -0
- data/lib/rom/commands/lazy/delete.rb +10 -0
- data/lib/rom/commands/lazy/update.rb +10 -0
- data/lib/rom/configuration.rb +34 -14
- data/lib/rom/configuration_dsl.rb +0 -2
- data/lib/rom/constants.rb +10 -0
- data/lib/rom/container.rb +16 -0
- data/lib/rom/create_container.rb +7 -0
- data/lib/rom/environment.rb +3 -2
- data/lib/rom/gateway.rb +16 -1
- data/lib/rom/global.rb +1 -1
- data/lib/rom/global/plugin_dsl.rb +3 -1
- data/lib/rom/initializer.rb +25 -13
- data/lib/rom/mapper_registry.rb +4 -1
- data/lib/rom/memory/dataset.rb +29 -2
- data/lib/rom/memory/schema.rb +7 -0
- data/lib/rom/plugin_base.rb +1 -1
- data/lib/rom/plugin_registry.rb +2 -2
- data/lib/rom/plugins/command/schema.rb +7 -0
- data/lib/rom/plugins/relation/instrumentation.rb +10 -0
- data/lib/rom/plugins/relation/registry_reader.rb +0 -3
- data/lib/rom/registry.rb +15 -3
- data/lib/rom/relation.rb +38 -23
- data/lib/rom/relation/class_interface.rb +15 -6
- data/lib/rom/relation/combined.rb +7 -2
- data/lib/rom/relation/curried.rb +23 -0
- data/lib/rom/relation/graph.rb +25 -14
- data/lib/rom/relation/loaded.rb +7 -4
- data/lib/rom/relation/materializable.rb +2 -2
- data/lib/rom/relation/view_dsl.rb +2 -1
- data/lib/rom/relation/wrap.rb +14 -0
- data/lib/rom/relation_registry.rb +2 -0
- data/lib/rom/schema.rb +25 -4
- data/lib/rom/schema/associations_dsl.rb +9 -0
- data/lib/rom/schema/dsl.rb +27 -4
- data/lib/rom/setup.rb +20 -7
- data/lib/rom/setup/auto_registration.rb +27 -0
- data/lib/rom/setup/auto_registration_strategies/base.rb +7 -2
- data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +17 -0
- data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +11 -0
- data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +9 -0
- data/lib/rom/setup/finalize/finalize_mappers.rb +4 -2
- data/lib/rom/setup/finalize/finalize_relations.rb +1 -1
- data/lib/rom/support/configurable.rb +19 -0
- data/lib/rom/support/notifications.rb +29 -2
- data/lib/rom/types.rb +53 -8
- data/lib/rom/version.rb +1 -1
- metadata +7 -13
@@ -2,17 +2,35 @@ require 'rom/associations/abstract'
|
|
2
2
|
|
3
3
|
module ROM
|
4
4
|
module Associations
|
5
|
+
# Abstract one-to-many association
|
6
|
+
#
|
7
|
+
# @api public
|
5
8
|
class OneToMany < Abstract
|
9
|
+
# Adapters must implement this method
|
10
|
+
#
|
11
|
+
# @abstract
|
12
|
+
#
|
6
13
|
# @api public
|
7
14
|
def call(*)
|
8
15
|
raise NotImplementedError
|
9
16
|
end
|
10
17
|
|
18
|
+
# Return configured or inferred FK name
|
19
|
+
#
|
20
|
+
# @return [Symbol]
|
21
|
+
#
|
11
22
|
# @api public
|
12
23
|
def foreign_key
|
13
24
|
definition.foreign_key || target.foreign_key(source.name)
|
14
25
|
end
|
15
26
|
|
27
|
+
# Associate child tuple with a parent
|
28
|
+
#
|
29
|
+
# @param [Hash] child The child tuple
|
30
|
+
# @param [Hash] parent The parent tuple
|
31
|
+
#
|
32
|
+
# @return [Hash]
|
33
|
+
#
|
16
34
|
# @api private
|
17
35
|
def associate(child, parent)
|
18
36
|
pk, fk = join_key_map
|
@@ -21,11 +39,19 @@ module ROM
|
|
21
39
|
|
22
40
|
protected
|
23
41
|
|
42
|
+
# Return primary key on the source side
|
43
|
+
#
|
44
|
+
# @return [Symbol]
|
45
|
+
#
|
24
46
|
# @api protected
|
25
47
|
def source_key
|
26
48
|
source.schema.primary_key_name
|
27
49
|
end
|
28
50
|
|
51
|
+
# Return foreign key name on the target side
|
52
|
+
#
|
53
|
+
# @return [Symbol]
|
54
|
+
#
|
29
55
|
# @api protected
|
30
56
|
def target_key
|
31
57
|
foreign_key
|
data/lib/rom/attribute.rb
CHANGED
@@ -20,7 +20,7 @@ module ROM
|
|
20
20
|
extend Initializer
|
21
21
|
|
22
22
|
# @!attribute [r] type
|
23
|
-
# @return [Dry::Types::Definition, Dry::Types::Sum, Dry::Types::Constrained]
|
23
|
+
# @return [Dry::Types::Definition, Dry::Types::Sum, Dry::Types::Constrained] The attribute's type object
|
24
24
|
param :type
|
25
25
|
|
26
26
|
# @api private
|
@@ -336,7 +336,7 @@ module ROM
|
|
336
336
|
|
337
337
|
# Check if the attribute type is equal to another
|
338
338
|
#
|
339
|
-
# @param [Dry::Type, Attribute]
|
339
|
+
# @param [Dry::Type, Attribute] other
|
340
340
|
#
|
341
341
|
# @return [TrueClass,FalseClass]
|
342
342
|
#
|
data/lib/rom/auto_curry.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module ROM
|
2
|
+
# Relation extension which provides auto-currying of relation view methods
|
3
|
+
#
|
4
|
+
# @api private
|
2
5
|
module AutoCurry
|
3
6
|
def self.extended(klass)
|
4
7
|
klass.define_singleton_method(:method_added) do |name|
|
@@ -8,6 +11,7 @@ module ROM
|
|
8
11
|
end
|
9
12
|
end
|
10
13
|
|
14
|
+
# @api private
|
11
15
|
def auto_curry_guard
|
12
16
|
@__auto_curry_busy__ = true
|
13
17
|
yield
|
@@ -15,14 +19,21 @@ module ROM
|
|
15
19
|
@__auto_curry_busy__ = false
|
16
20
|
end
|
17
21
|
|
22
|
+
# @api private
|
18
23
|
def auto_curry_busy?
|
19
24
|
@__auto_curry_busy__ ||= false
|
20
25
|
end
|
21
26
|
|
27
|
+
# @api private
|
22
28
|
def auto_curried_methods
|
23
29
|
@__auto_curried_methods__ ||= Set.new
|
24
30
|
end
|
25
31
|
|
32
|
+
# Auto-curry a method
|
33
|
+
#
|
34
|
+
# @param [Symbol] name The name of a method
|
35
|
+
#
|
36
|
+
# @api private
|
26
37
|
def auto_curry(name, &block)
|
27
38
|
arity = instance_method(name).arity
|
28
39
|
|
data/lib/rom/cache.rb
CHANGED
@@ -1,27 +1,45 @@
|
|
1
1
|
require 'concurrent/map'
|
2
2
|
|
3
3
|
module ROM
|
4
|
+
# Thread-safe cache used by various rom components
|
5
|
+
#
|
4
6
|
# @api private
|
5
7
|
class Cache
|
6
8
|
attr_reader :objects
|
7
9
|
|
10
|
+
# @api private
|
8
11
|
class Namespaced
|
12
|
+
# @api private
|
9
13
|
attr_reader :cache
|
10
14
|
|
15
|
+
# @api private
|
11
16
|
attr_reader :namespace
|
12
17
|
|
18
|
+
# @api private
|
13
19
|
def initialize(cache, namespace)
|
14
20
|
@cache = cache
|
15
21
|
@namespace = namespace.to_sym
|
16
22
|
end
|
17
23
|
|
24
|
+
# @api private
|
18
25
|
def [](key)
|
19
26
|
cache[[namespace, key].hash]
|
20
27
|
end
|
21
28
|
|
29
|
+
# @api private
|
22
30
|
def fetch_or_store(*args, &block)
|
23
31
|
cache.fetch_or_store([namespace, args.hash].hash, &block)
|
24
32
|
end
|
33
|
+
|
34
|
+
# @api private
|
35
|
+
def size
|
36
|
+
cache.size
|
37
|
+
end
|
38
|
+
|
39
|
+
# @api private
|
40
|
+
def inspect
|
41
|
+
%(#<#{self.class} size=#{size}>)
|
42
|
+
end
|
25
43
|
end
|
26
44
|
|
27
45
|
# @api private
|
@@ -39,8 +57,19 @@ module ROM
|
|
39
57
|
objects.fetch_or_store(args.hash, &block)
|
40
58
|
end
|
41
59
|
|
60
|
+
# @api private
|
61
|
+
def size
|
62
|
+
objects.size
|
63
|
+
end
|
64
|
+
|
65
|
+
# @api private
|
42
66
|
def namespaced(namespace)
|
43
67
|
@namespaced[namespace] ||= Namespaced.new(objects, namespace)
|
44
68
|
end
|
69
|
+
|
70
|
+
# @api private
|
71
|
+
def inspect
|
72
|
+
%(#<#{self.class} size=#{size} namespaced=#{@namespaced.inspect}>)
|
73
|
+
end
|
45
74
|
end
|
46
75
|
end
|
data/lib/rom/command_compiler.rb
CHANGED
@@ -23,15 +23,15 @@ module ROM
|
|
23
23
|
end
|
24
24
|
|
25
25
|
# @!attribute [r] gateways
|
26
|
-
# @return [ROM::Registry]
|
26
|
+
# @return [ROM::Registry] Gateways used for command extensions
|
27
27
|
param :gateways
|
28
28
|
|
29
29
|
# @!attribute [r] relations
|
30
|
-
# @return [ROM::RelationRegistry]
|
30
|
+
# @return [ROM::RelationRegistry] Relations used with a given compiler
|
31
31
|
param :relations
|
32
32
|
|
33
|
-
# @!attribute [r]
|
34
|
-
# @return [ROM::Registry]
|
33
|
+
# @!attribute [r] commands
|
34
|
+
# @return [ROM::Registry] Command registries with custom commands
|
35
35
|
param :commands
|
36
36
|
|
37
37
|
# @!attribute [r] notifications
|
data/lib/rom/command_registry.rb
CHANGED
@@ -15,19 +15,23 @@ module ROM
|
|
15
15
|
# @api private
|
16
16
|
param :elements
|
17
17
|
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# @return [String]
|
21
|
-
#
|
22
|
-
# @api private
|
18
|
+
# @!attribute [r] relation_name
|
19
|
+
# @return [Relation::Name] The name of a relation
|
23
20
|
option :relation_name
|
24
21
|
|
22
|
+
# @!attribute [r] mappers
|
23
|
+
# @return [MapperRegistry] Optional mapper registry
|
25
24
|
option :mappers, optional: true
|
26
25
|
|
26
|
+
# @!attribute [r] mapper
|
27
|
+
# @return [Object#call] Default mapper for processing command results
|
27
28
|
option :mapper, optional: true
|
28
29
|
|
30
|
+
# @!attribute [r] compiler
|
31
|
+
# @return [CommandCompiler] A command compiler instance
|
29
32
|
option :compiler, optional: true
|
30
33
|
|
34
|
+
# @api private
|
31
35
|
def self.element_not_found_error
|
32
36
|
CommandNotFoundError
|
33
37
|
end
|
@@ -75,12 +75,12 @@ module ROM
|
|
75
75
|
|
76
76
|
# Create a command class with a specific type
|
77
77
|
#
|
78
|
-
# @param [Symbol]
|
79
|
-
# @param [Class]
|
78
|
+
# @param [Symbol] name Command name
|
79
|
+
# @param [Class] type Command class
|
80
80
|
#
|
81
|
-
# @yield [Class]
|
81
|
+
# @yield [Class]
|
82
82
|
#
|
83
|
-
# @return [Class, Object]
|
83
|
+
# @return [Class, Object]
|
84
84
|
#
|
85
85
|
# @api public
|
86
86
|
def create_class(name, type, &block)
|
@@ -105,8 +105,8 @@ module ROM
|
|
105
105
|
# end
|
106
106
|
#
|
107
107
|
# @param [Symbol] plugin
|
108
|
-
# @param [Hash]
|
109
|
-
# @option
|
108
|
+
# @param [Hash] _options
|
109
|
+
# @option _options [Symbol] :adapter (:default) first adapter to check for plugin
|
110
110
|
#
|
111
111
|
# @api public
|
112
112
|
def use(plugin, _options = EMPTY_HASH)
|
@@ -115,7 +115,7 @@ module ROM
|
|
115
115
|
|
116
116
|
# Extend a command class with relation view methods
|
117
117
|
#
|
118
|
-
# @param [Relation]
|
118
|
+
# @param [Relation] relation
|
119
119
|
#
|
120
120
|
# @return [Class]
|
121
121
|
#
|
@@ -1,19 +1,37 @@
|
|
1
1
|
module ROM
|
2
2
|
module Commands
|
3
3
|
class Graph
|
4
|
+
# Evaluator for lazy commands which extracts values for commands from nested hashes
|
5
|
+
#
|
6
|
+
# @api private
|
4
7
|
class InputEvaluator
|
5
8
|
include Dry::Equalizer(:tuple_path, :excluded_keys)
|
6
9
|
|
10
|
+
# @!attribute [r] tuple_path
|
11
|
+
# @return [Array<Symbol>] A list of keys pointing to a value inside a hash
|
7
12
|
attr_reader :tuple_path
|
8
13
|
|
14
|
+
# @!attribute [r] excluded_keys
|
15
|
+
# @return [Array<Symbol>] A list of keys that should be excluded
|
9
16
|
attr_reader :excluded_keys
|
10
17
|
|
18
|
+
# @!attribute [r] exclude_proc
|
19
|
+
# @return [Array<Symbol>] A function that should determine which keys should be excluded
|
11
20
|
attr_reader :exclude_proc
|
12
21
|
|
22
|
+
# Build an input evaluator
|
23
|
+
#
|
24
|
+
# @param [Array<Symbol>] tuple_path The tuple path
|
25
|
+
# @param [Array] nodes
|
26
|
+
#
|
27
|
+
# @return [InputEvaluator]
|
28
|
+
#
|
29
|
+
# @api private
|
13
30
|
def self.build(tuple_path, nodes)
|
14
31
|
new(tuple_path, extract_excluded_keys(nodes))
|
15
32
|
end
|
16
33
|
|
34
|
+
# @api private
|
17
35
|
def self.extract_excluded_keys(nodes)
|
18
36
|
return unless nodes
|
19
37
|
|
@@ -24,19 +42,31 @@ module ROM
|
|
24
42
|
.reject { |item| item.is_a?(Array) }
|
25
43
|
end
|
26
44
|
|
45
|
+
# Return default exclude_proc
|
46
|
+
#
|
47
|
+
# @api private
|
27
48
|
def self.exclude_proc(excluded_keys)
|
28
49
|
-> input { input.reject { |k, _| excluded_keys.include?(k) } }
|
29
50
|
end
|
30
51
|
|
52
|
+
# Initialize a new input evaluator
|
53
|
+
#
|
54
|
+
# @return [InputEvaluator]
|
55
|
+
#
|
56
|
+
# @api private
|
31
57
|
def initialize(tuple_path, excluded_keys)
|
32
58
|
@tuple_path = tuple_path
|
33
59
|
@excluded_keys = excluded_keys
|
34
60
|
@exclude_proc = self.class.exclude_proc(excluded_keys)
|
35
61
|
end
|
36
62
|
|
37
|
-
|
38
|
-
|
39
|
-
|
63
|
+
# Evaluate input hash
|
64
|
+
#
|
65
|
+
# @param [Hash] input The input hash
|
66
|
+
# @param [Integer] index Optional index
|
67
|
+
#
|
68
|
+
# @return [Hash]
|
69
|
+
def call(input, index = nil)
|
40
70
|
value =
|
41
71
|
begin
|
42
72
|
if index
|
data/lib/rom/commands/lazy.rb
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
module ROM
|
2
2
|
module Commands
|
3
3
|
class Lazy
|
4
|
+
# Lazy command wrapper for create commands
|
5
|
+
#
|
6
|
+
# @api public
|
4
7
|
class Create < Lazy
|
8
|
+
# Execute a command
|
9
|
+
#
|
10
|
+
# @see Command::Create#call
|
11
|
+
#
|
12
|
+
# @return [Hash,Array<Hash>]
|
13
|
+
#
|
14
|
+
# @api public
|
5
15
|
def call(*args)
|
6
16
|
first = args.first
|
7
17
|
last = args.last
|
@@ -1,7 +1,17 @@
|
|
1
1
|
module ROM
|
2
2
|
module Commands
|
3
3
|
class Lazy
|
4
|
+
# Lazy command wrapper for delete commands
|
5
|
+
#
|
6
|
+
# @api public
|
4
7
|
class Delete < Lazy
|
8
|
+
# Execute a lazy delete command
|
9
|
+
#
|
10
|
+
# @see Commands::Delete#call
|
11
|
+
#
|
12
|
+
# @return [Hash, Array<Hash>]
|
13
|
+
#
|
14
|
+
# @api public
|
5
15
|
def call(*args)
|
6
16
|
first = args.first
|
7
17
|
last = args.last
|
@@ -1,7 +1,17 @@
|
|
1
1
|
module ROM
|
2
2
|
module Commands
|
3
3
|
class Lazy
|
4
|
+
# Lazy command wrapper for update commands
|
5
|
+
#
|
6
|
+
# @api public
|
4
7
|
class Update < Lazy
|
8
|
+
# Execute a lazy update command
|
9
|
+
#
|
10
|
+
# @see Commands::Update#call
|
11
|
+
#
|
12
|
+
# @return [Hash, Array<Hash>]
|
13
|
+
#
|
14
|
+
# @api public
|
5
15
|
def call(*args)
|
6
16
|
first = args.first
|
7
17
|
last = args.last
|
data/lib/rom/configuration.rb
CHANGED
@@ -22,7 +22,17 @@ module ROM
|
|
22
22
|
|
23
23
|
NoDefaultAdapterError = Class.new(StandardError)
|
24
24
|
|
25
|
-
|
25
|
+
# @!attribute [r] environment
|
26
|
+
# @return [Environment] Environment object with gateways
|
27
|
+
attr_reader :environment
|
28
|
+
|
29
|
+
# @!attribute [r] setup
|
30
|
+
# @return [Setup] Setup object which collects component classes and plugins
|
31
|
+
attr_reader :setup
|
32
|
+
|
33
|
+
# @!attribute [r] notifications
|
34
|
+
# @return [Notifications] Notification bus instance
|
35
|
+
attr_reader :notifications
|
26
36
|
|
27
37
|
def_delegators :@setup, :register_relation, :register_command, :register_mapper, :register_plugin,
|
28
38
|
:command_classes, :mapper_classes,
|
@@ -30,7 +40,13 @@ module ROM
|
|
30
40
|
|
31
41
|
def_delegators :@environment, :gateways, :gateways_map, :configure, :config
|
32
42
|
|
33
|
-
#
|
43
|
+
# Initialize a new configuration
|
44
|
+
#
|
45
|
+
# @see Environment#initialize
|
46
|
+
#
|
47
|
+
# @return [Configuration]
|
48
|
+
#
|
49
|
+
# @api private
|
34
50
|
def initialize(*args, &block)
|
35
51
|
@environment = Environment.new(*args)
|
36
52
|
@notifications = Notifications.event_bus(:configuration)
|
@@ -38,13 +54,15 @@ module ROM
|
|
38
54
|
|
39
55
|
use :mappers # enable mappers by default
|
40
56
|
|
41
|
-
block.call(self)
|
57
|
+
block.call(self) if block
|
42
58
|
end
|
43
59
|
|
44
60
|
# Apply a plugin to the configuration
|
45
61
|
#
|
46
|
-
# @param [Mixed] The plugin identifier, usually a Symbol
|
47
|
-
# @param [Hash] Plugin options
|
62
|
+
# @param [Mixed] plugin The plugin identifier, usually a Symbol
|
63
|
+
# @param [Hash] options Plugin options
|
64
|
+
#
|
65
|
+
# @return [Configuration]
|
48
66
|
#
|
49
67
|
# @api public
|
50
68
|
def use(plugin, options = {})
|
@@ -68,15 +86,6 @@ module ROM
|
|
68
86
|
gateways.fetch(name)
|
69
87
|
end
|
70
88
|
|
71
|
-
# Returns gateway if method is a name of a registered gateway
|
72
|
-
#
|
73
|
-
# @return [Gateway]
|
74
|
-
#
|
75
|
-
# @api private
|
76
|
-
def method_missing(name, *)
|
77
|
-
gateways.fetch(name) { super }
|
78
|
-
end
|
79
|
-
|
80
89
|
# Hook for respond_to? used internally
|
81
90
|
#
|
82
91
|
# @api private
|
@@ -110,5 +119,16 @@ module ROM
|
|
110
119
|
def default_adapter
|
111
120
|
@default_adapter ||= adapter_for_gateway(default_gateway) || ROM.adapters.keys.first
|
112
121
|
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
# Returns gateway if method is a name of a registered gateway
|
126
|
+
#
|
127
|
+
# @return [Gateway]
|
128
|
+
#
|
129
|
+
# @api private
|
130
|
+
def method_missing(name, *)
|
131
|
+
gateways.fetch(name) { super }
|
132
|
+
end
|
113
133
|
end
|
114
134
|
end
|