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