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
@@ -9,7 +9,6 @@ module ROM
|
|
9
9
|
# Relation definition DSL
|
10
10
|
#
|
11
11
|
# @example
|
12
|
-
#
|
13
12
|
# setup.relation(:users) do
|
14
13
|
# def names
|
15
14
|
# project(:name)
|
@@ -29,7 +28,6 @@ module ROM
|
|
29
28
|
# Command definition DSL
|
30
29
|
#
|
31
30
|
# @example
|
32
|
-
#
|
33
31
|
# setup.commands(:users) do
|
34
32
|
# define(:create) do
|
35
33
|
# input NewUserParams
|
data/lib/rom/constants.rb
CHANGED
@@ -6,7 +6,9 @@ module ROM
|
|
6
6
|
|
7
7
|
AdapterLoadError = Class.new(StandardError)
|
8
8
|
|
9
|
+
# Exception raised when a component is configured with an adapter that's not loaded
|
9
10
|
class AdapterNotPresentError < StandardError
|
11
|
+
# @api private
|
10
12
|
def initialize(adapter, component)
|
11
13
|
super(
|
12
14
|
"Failed to find #{component} class for #{adapter} adapter. " \
|
@@ -28,17 +30,22 @@ module ROM
|
|
28
30
|
MissingAdapterIdentifierError = Class.new(StandardError)
|
29
31
|
AttributeAlreadyDefinedError = Class.new(StandardError)
|
30
32
|
|
33
|
+
# Exception raised when a reserved keyword is used as a relation name
|
31
34
|
class InvalidRelationName < StandardError
|
35
|
+
# @api private
|
32
36
|
def initialize(relation)
|
33
37
|
super("Relation name: #{relation} is a protected word, please use another relation name")
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
41
|
+
# Exception raised when an element inside a component registry is not found
|
37
42
|
class ElementNotFoundError < KeyError
|
43
|
+
# @api private
|
38
44
|
def initialize(key, registry)
|
39
45
|
super(set_message(key, registry))
|
40
46
|
end
|
41
47
|
|
48
|
+
# @api private
|
42
49
|
def set_message(key, registry)
|
43
50
|
"#{key.inspect} doesn't exist in #{registry.class.name} registry"
|
44
51
|
end
|
@@ -47,18 +54,21 @@ module ROM
|
|
47
54
|
MapperMissingError = Class.new(ElementNotFoundError)
|
48
55
|
|
49
56
|
CommandNotFoundError = Class.new(ElementNotFoundError) do
|
57
|
+
# @api private
|
50
58
|
def set_message(key, registry)
|
51
59
|
"There is no :#{key} command for :#{registry.relation_name} relation"
|
52
60
|
end
|
53
61
|
end
|
54
62
|
|
55
63
|
MissingSchemaClassError = Class.new(StandardError) do
|
64
|
+
# @api private
|
56
65
|
def initialize(klass)
|
57
66
|
super("#{klass.inspect} relation is missing schema_class")
|
58
67
|
end
|
59
68
|
end
|
60
69
|
|
61
70
|
MissingSchemaError = Class.new(StandardError) do
|
71
|
+
# @api private
|
62
72
|
def initialize(klass)
|
63
73
|
super("#{klass.inspect} relation is missing schema definition")
|
64
74
|
end
|
data/lib/rom/container.rb
CHANGED
@@ -110,21 +110,37 @@ module ROM
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
+
# Return registered gateways
|
114
|
+
#
|
115
|
+
# @return [Hash<Symbol=>Gateway>]
|
116
|
+
#
|
113
117
|
# @api public
|
114
118
|
def gateways
|
115
119
|
self[:gateways]
|
116
120
|
end
|
117
121
|
|
122
|
+
# Return mapper registry for all relations
|
123
|
+
#
|
124
|
+
# @return [Hash<Symbol=>MapperRegistry]
|
125
|
+
#
|
118
126
|
# @api public
|
119
127
|
def mappers
|
120
128
|
self[:mappers]
|
121
129
|
end
|
122
130
|
|
131
|
+
# Return relation registry
|
132
|
+
#
|
133
|
+
# @return [RelationRegistry]
|
134
|
+
#
|
123
135
|
# @api public
|
124
136
|
def relations
|
125
137
|
self[:relations]
|
126
138
|
end
|
127
139
|
|
140
|
+
# Return command registry
|
141
|
+
#
|
142
|
+
# @return [Hash<Symbol=>CommandRegistry]
|
143
|
+
#
|
128
144
|
# @api public
|
129
145
|
def commands
|
130
146
|
self[:commands]
|
data/lib/rom/create_container.rb
CHANGED
@@ -4,15 +4,19 @@ require 'rom/setup'
|
|
4
4
|
require 'rom/setup/finalize'
|
5
5
|
|
6
6
|
module ROM
|
7
|
+
# @api private
|
7
8
|
class CreateContainer
|
9
|
+
# @api private
|
8
10
|
attr_reader :container
|
9
11
|
|
12
|
+
# @api private
|
10
13
|
def initialize(environment, setup)
|
11
14
|
@container = finalize(environment, setup)
|
12
15
|
end
|
13
16
|
|
14
17
|
private
|
15
18
|
|
19
|
+
# @api private
|
16
20
|
def finalize(environment, setup)
|
17
21
|
environment.configure do |config|
|
18
22
|
environment.gateways.each_key do |key|
|
@@ -35,7 +39,9 @@ module ROM
|
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
42
|
+
# @api private
|
38
43
|
class InlineCreateContainer < CreateContainer
|
44
|
+
# @api private
|
39
45
|
def initialize(*args, &block)
|
40
46
|
case args.first
|
41
47
|
when Configuration
|
@@ -54,6 +60,7 @@ module ROM
|
|
54
60
|
end
|
55
61
|
end
|
56
62
|
|
63
|
+
# @api private
|
57
64
|
def self.container(*args, &block)
|
58
65
|
InlineCreateContainer.new(*args, &block).container
|
59
66
|
end
|
data/lib/rom/environment.rb
CHANGED
@@ -4,13 +4,13 @@ require 'rom/gateway'
|
|
4
4
|
module ROM
|
5
5
|
# Core gateway configuration interface
|
6
6
|
#
|
7
|
-
# @api
|
7
|
+
# @api private
|
8
8
|
class Environment
|
9
9
|
include Configurable
|
10
10
|
|
11
11
|
attr_reader :gateways, :gateways_map
|
12
12
|
|
13
|
-
# @api
|
13
|
+
# @api private
|
14
14
|
def initialize(*args)
|
15
15
|
@gateways = {}
|
16
16
|
@gateways_map = {}
|
@@ -20,6 +20,7 @@ module ROM
|
|
20
20
|
|
21
21
|
private
|
22
22
|
|
23
|
+
# @api private
|
23
24
|
def configure_gateways(*args)
|
24
25
|
normalized_gateway_args = normalize_gateway_args(*args)
|
25
26
|
normalized_gateways = normalize_gateways(normalized_gateway_args)
|
data/lib/rom/gateway.rb
CHANGED
@@ -16,6 +16,20 @@ module ROM
|
|
16
16
|
extend Dry::Core::ClassAttributes
|
17
17
|
extend Notifications::Listener
|
18
18
|
|
19
|
+
# @!method self.adapter
|
20
|
+
# Get or set gateway's adapter identifier
|
21
|
+
#
|
22
|
+
# @overload adapter
|
23
|
+
# Return adapter identifier
|
24
|
+
# @return [Symbol]
|
25
|
+
#
|
26
|
+
# @overload gateway(adapter)
|
27
|
+
# @example
|
28
|
+
# class MyGateway < ROM::Gateway
|
29
|
+
# adapter :my_adapter
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# @param [Symbol] adapter The adapter identifier
|
19
33
|
defines :adapter
|
20
34
|
|
21
35
|
# @!attribute [r] connection
|
@@ -154,7 +168,8 @@ module ROM
|
|
154
168
|
# Runs a block inside a transaction. The underlying transaction engine
|
155
169
|
# is adapter-specific
|
156
170
|
#
|
157
|
-
# @param [Hash] Transaction options
|
171
|
+
# @param [Hash] opts Transaction options
|
172
|
+
#
|
158
173
|
# @return The result of yielding the block or +nil+ if
|
159
174
|
# the transaction was rolled back
|
160
175
|
#
|
data/lib/rom/global.rb
CHANGED
data/lib/rom/initializer.rb
CHANGED
@@ -1,29 +1,28 @@
|
|
1
1
|
require 'dry-initializer'
|
2
2
|
|
3
3
|
module ROM
|
4
|
-
|
5
4
|
# @api private
|
6
5
|
module Initializer
|
7
6
|
# @api private
|
8
7
|
module DefineWithHook
|
8
|
+
# @api private
|
9
9
|
def param(*)
|
10
|
-
super
|
11
|
-
|
12
|
-
__define_with__
|
10
|
+
super.tap { __define_with__ }
|
13
11
|
end
|
14
12
|
|
13
|
+
# @api private
|
15
14
|
def option(*)
|
16
|
-
super
|
17
|
-
|
18
|
-
|
15
|
+
super.tap do
|
16
|
+
__define_with__ unless method_defined?(:with)
|
17
|
+
end
|
19
18
|
end
|
20
19
|
|
20
|
+
# @api private
|
21
21
|
def __define_with__
|
22
|
-
seq_names =
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
map { |_, name| name }.
|
22
|
+
seq_names = dry_initializer.
|
23
|
+
definitions.
|
24
|
+
reject { |_, d| d.option }.
|
25
|
+
keys.
|
27
26
|
join(', ')
|
28
27
|
|
29
28
|
seq_names << ', ' unless seq_names.empty?
|
@@ -57,7 +56,20 @@ module ROM
|
|
57
56
|
#
|
58
57
|
# @api public
|
59
58
|
def options
|
60
|
-
@__options__
|
59
|
+
@__options__ ||= self.class.dry_initializer.definitions.values.each_with_object({}) do |item, obj|
|
60
|
+
obj[item.target] = instance_variable_get(item.ivar)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
define_method(:class, Kernel.instance_method(:class))
|
65
|
+
define_method(:instance_variable_get, Kernel.instance_method(:instance_variable_get))
|
66
|
+
|
67
|
+
# This makes sure we memoize options before an object becomes frozen
|
68
|
+
#
|
69
|
+
# @api public
|
70
|
+
def freeze
|
71
|
+
options
|
72
|
+
super
|
61
73
|
end
|
62
74
|
end
|
63
75
|
end
|
data/lib/rom/mapper_registry.rb
CHANGED
@@ -5,11 +5,14 @@ require 'rom/mapper_compiler'
|
|
5
5
|
module ROM
|
6
6
|
# @private
|
7
7
|
class MapperRegistry < Registry
|
8
|
+
# @api private
|
8
9
|
def self.element_not_found_error
|
9
10
|
MapperMissingError
|
10
11
|
end
|
11
12
|
|
12
|
-
|
13
|
+
# @!attribute [r] compiler
|
14
|
+
# @return [MapperCompiler] A mapper compiler instance
|
15
|
+
option :compiler, default: -> { MapperCompiler.new(cache: cache) }
|
13
16
|
|
14
17
|
# @see Registry
|
15
18
|
# @api public
|
data/lib/rom/memory/dataset.rb
CHANGED
@@ -4,11 +4,17 @@ module ROM
|
|
4
4
|
module Memory
|
5
5
|
# In-memory dataset
|
6
6
|
#
|
7
|
+
# This class can be used as a base class for other adapters.
|
8
|
+
#
|
7
9
|
# @api public
|
8
10
|
class Dataset
|
9
11
|
include ArrayDataset
|
10
12
|
|
11
|
-
# Join
|
13
|
+
# Join with other datasets
|
14
|
+
#
|
15
|
+
# @param [Array<Dataset>] args A list of dataset to join with
|
16
|
+
#
|
17
|
+
# @return [Dataset]
|
12
18
|
#
|
13
19
|
# @api public
|
14
20
|
def join(*args)
|
@@ -28,9 +34,14 @@ module ROM
|
|
28
34
|
|
29
35
|
# Restrict a dataset
|
30
36
|
#
|
37
|
+
# @param [Hash] criteria A hash with conditions
|
38
|
+
#
|
39
|
+
# @return [Dataset]
|
40
|
+
#
|
31
41
|
# @api public
|
32
42
|
def restrict(criteria = nil)
|
33
43
|
return find_all { |tuple| yield(tuple) } unless criteria
|
44
|
+
|
34
45
|
find_all do |tuple|
|
35
46
|
criteria.all? do |k, v|
|
36
47
|
case v
|
@@ -44,6 +55,10 @@ module ROM
|
|
44
55
|
|
45
56
|
# Project a dataset
|
46
57
|
#
|
58
|
+
# @param [Array<Symbol>] names A list of attribute names
|
59
|
+
#
|
60
|
+
# @return [Dataset]
|
61
|
+
#
|
47
62
|
# @api public
|
48
63
|
def project(*names)
|
49
64
|
map { |tuple| tuple.reject { |key| !names.include?(key) } }
|
@@ -51,12 +66,14 @@ module ROM
|
|
51
66
|
|
52
67
|
# Sort a dataset
|
53
68
|
#
|
54
|
-
# @param [Array<Symbol>]
|
69
|
+
# @param [Array<Symbol>] fields
|
55
70
|
# Names of fields to order tuples by
|
56
71
|
#
|
57
72
|
# @option [Boolean] :nils_first (false)
|
58
73
|
# Whether `nil` values should be placed before others
|
59
74
|
#
|
75
|
+
# @return [Dataset]
|
76
|
+
#
|
60
77
|
# @api public
|
61
78
|
def order(*fields)
|
62
79
|
nils_first = fields.pop[:nils_first] if fields.last.is_a?(Hash)
|
@@ -70,7 +87,11 @@ module ROM
|
|
70
87
|
|
71
88
|
# Insert tuple into a dataset
|
72
89
|
#
|
90
|
+
# @param [Hash] tuple A new tuple for insertion
|
91
|
+
#
|
73
92
|
# @api public
|
93
|
+
#
|
94
|
+
# @return [Dataset]
|
74
95
|
def insert(tuple)
|
75
96
|
data << tuple
|
76
97
|
self
|
@@ -79,6 +100,10 @@ module ROM
|
|
79
100
|
|
80
101
|
# Delete tuples from a dataset
|
81
102
|
#
|
103
|
+
# @param [Hash] tuple A new tuple for deletion
|
104
|
+
#
|
105
|
+
# @return [Dataset]
|
106
|
+
#
|
82
107
|
# @api public
|
83
108
|
def delete(tuple)
|
84
109
|
data.delete(tuple)
|
@@ -88,6 +113,8 @@ module ROM
|
|
88
113
|
private
|
89
114
|
|
90
115
|
# Compares two values, that are either comparable, or can be nils
|
116
|
+
#
|
117
|
+
# @api private
|
91
118
|
def __compare__(a, b, nils_first)
|
92
119
|
return a <=> b unless a.nil? ^ b.nil?
|
93
120
|
(nils_first ^ b.nil?) ? -1 : 1
|
data/lib/rom/memory/schema.rb
CHANGED
@@ -3,6 +3,9 @@ require 'rom/memory/associations'
|
|
3
3
|
|
4
4
|
module ROM
|
5
5
|
module Memory
|
6
|
+
# Specialized schema for memory adapter
|
7
|
+
#
|
8
|
+
# @api public
|
6
9
|
class Schema < ROM::Schema
|
7
10
|
# @see Schema#call
|
8
11
|
# @api public
|
@@ -10,6 +13,10 @@ module ROM
|
|
10
13
|
relation.new(relation.dataset.project(*map(&:name)), schema: self)
|
11
14
|
end
|
12
15
|
|
16
|
+
# Internal hook used during setup process
|
17
|
+
#
|
18
|
+
# @see Schema#finalize_associations!
|
19
|
+
#
|
13
20
|
# @api private
|
14
21
|
def finalize_associations!(relations:)
|
15
22
|
super do
|
data/lib/rom/plugin_base.rb
CHANGED
data/lib/rom/plugin_registry.rb
CHANGED
@@ -137,7 +137,7 @@ module ROM
|
|
137
137
|
#
|
138
138
|
# @param [Symbol] name The name of the environment plugin
|
139
139
|
#
|
140
|
-
# @
|
140
|
+
# @raise [UnknownPluginError] if no plugin is found with the given name
|
141
141
|
#
|
142
142
|
# @api public
|
143
143
|
def fetch(name)
|
@@ -184,7 +184,7 @@ module ROM
|
|
184
184
|
# @param [Symbol] name The name of the plugin
|
185
185
|
# @param [Symbol] adapter_name (:default) The name of the adapter used
|
186
186
|
#
|
187
|
-
# @
|
187
|
+
# @raise [UnknownPluginError] if no plugin is found with the given name
|
188
188
|
#
|
189
189
|
# @api public
|
190
190
|
def fetch(name, adapter_name = :default)
|