rom 0.9.1 → 1.0.0.beta1
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/.rubocop_todo.yml +30 -12
- data/.travis.yml +1 -1
- data/CHANGELOG.md +24 -0
- data/Gemfile +7 -3
- data/README.md +24 -11
- data/lib/rom.rb +9 -26
- data/lib/rom/command.rb +113 -75
- data/lib/rom/commands/class_interface.rb +115 -0
- data/lib/rom/commands/graph.rb +17 -23
- data/lib/rom/commands/graph/builder.rb +176 -0
- data/lib/rom/commands/graph/class_interface.rb +8 -2
- data/lib/rom/commands/graph/input_evaluator.rb +13 -9
- data/lib/rom/commands/lazy.rb +23 -17
- data/lib/rom/commands/lazy/create.rb +23 -0
- data/lib/rom/commands/lazy/delete.rb +27 -0
- data/lib/rom/commands/lazy/update.rb +34 -0
- data/lib/rom/commands/result.rb +14 -0
- data/lib/rom/commands/update.rb +0 -4
- data/lib/rom/configuration.rb +86 -0
- data/lib/rom/{setup_dsl/setup.rb → configuration_dsl.rb} +9 -7
- data/lib/rom/configuration_dsl/command.rb +43 -0
- data/lib/rom/{setup_dsl → configuration_dsl}/command_dsl.rb +5 -4
- data/lib/rom/configuration_dsl/mapper.rb +37 -0
- data/lib/rom/{setup_dsl → configuration_dsl}/mapper_dsl.rb +11 -5
- data/lib/rom/configuration_dsl/relation.rb +26 -0
- data/lib/rom/configuration_plugin.rb +17 -0
- data/lib/rom/constants.rb +5 -12
- data/lib/rom/container.rb +11 -8
- data/lib/rom/create_container.rb +61 -0
- data/lib/rom/environment.rb +27 -241
- data/lib/rom/gateway.rb +18 -2
- data/lib/rom/global.rb +24 -0
- data/lib/rom/global/plugin_dsl.rb +2 -0
- data/lib/rom/lint/spec.rb +0 -12
- data/lib/rom/lint/test.rb +0 -31
- data/lib/rom/memory/commands.rb +2 -2
- data/lib/rom/memory/gateway.rb +2 -0
- data/lib/rom/pipeline.rb +1 -1
- data/lib/rom/plugin_base.rb +1 -1
- data/lib/rom/plugin_registry.rb +12 -10
- data/lib/rom/plugins/configuration/configuration_dsl.rb +16 -0
- data/lib/rom/plugins/relation/key_inference.rb +31 -0
- data/lib/rom/plugins/relation/view.rb +90 -0
- data/lib/rom/plugins/relation/view/dsl.rb +32 -0
- data/lib/rom/relation.rb +1 -11
- data/lib/rom/relation/class_interface.rb +37 -50
- data/lib/rom/setup.rb +13 -104
- data/lib/rom/setup/auto_registration.rb +55 -0
- data/lib/rom/setup/finalize.rb +113 -127
- data/lib/rom/setup/finalize/commands.rb +67 -0
- data/lib/rom/setup/finalize/mappers.rb +36 -0
- data/lib/rom/setup/finalize/relations.rb +53 -0
- data/lib/rom/support/configurable.rb +21 -7
- data/lib/rom/version.rb +1 -1
- data/rakelib/mutant.rake +4 -1
- data/rom.gemspec +3 -4
- data/spec/fixtures/app/commands/create_user.rb +2 -0
- data/spec/fixtures/app/mappers/user_list.rb +2 -0
- data/spec/fixtures/app/relations/users.rb +2 -0
- data/spec/fixtures/lib/persistence/commands/create_user.rb +6 -0
- data/spec/fixtures/lib/persistence/mappers/user_list.rb +6 -0
- data/spec/fixtures/lib/persistence/relations/users.rb +6 -0
- data/spec/{unit/rom → integration}/command_registry_spec.rb +8 -9
- data/spec/integration/commands/create_spec.rb +17 -13
- data/spec/integration/commands/delete_spec.rb +12 -11
- data/spec/integration/commands/error_handling_spec.rb +5 -4
- data/spec/integration/commands/graph_builder_spec.rb +213 -0
- data/spec/integration/commands/graph_spec.rb +112 -49
- data/spec/integration/commands/update_spec.rb +14 -11
- data/spec/integration/commands_spec.rb +60 -0
- data/spec/integration/mappers/combine_spec.rb +7 -6
- data/spec/integration/mappers/deep_embedded_spec.rb +5 -6
- data/spec/integration/mappers/definition_dsl_spec.rb +19 -18
- data/spec/integration/mappers/embedded_spec.rb +11 -12
- data/spec/integration/mappers/exclude_spec.rb +5 -6
- data/spec/integration/mappers/fold_spec.rb +8 -7
- data/spec/integration/mappers/group_spec.rb +16 -15
- data/spec/integration/mappers/overwrite_attributes_value_spec.rb +5 -5
- data/spec/integration/mappers/prefix_separator_spec.rb +5 -7
- data/spec/integration/mappers/prefix_spec.rb +5 -7
- data/spec/integration/mappers/prefixing_attributes_spec.rb +7 -7
- data/spec/integration/mappers/registering_custom_mappers_spec.rb +4 -5
- data/spec/integration/mappers/renaming_attributes_spec.rb +18 -18
- data/spec/integration/mappers/step_spec.rb +11 -12
- data/spec/integration/mappers/symbolizing_attributes_spec.rb +11 -8
- data/spec/integration/mappers/unfold_spec.rb +9 -10
- data/spec/integration/mappers/ungroup_spec.rb +10 -11
- data/spec/integration/mappers/unwrap_spec.rb +10 -15
- data/spec/integration/mappers/wrap_spec.rb +16 -15
- data/spec/{unit/rom → integration}/memory/commands/create_spec.rb +7 -5
- data/spec/{unit/rom → integration}/memory/commands/delete_spec.rb +7 -5
- data/spec/{unit/rom → integration}/memory/commands/update_spec.rb +7 -5
- data/spec/integration/multi_env_spec.rb +16 -124
- data/spec/integration/multi_repo_spec.rb +9 -9
- data/spec/integration/relations/default_dataset_spec.rb +15 -0
- data/spec/integration/relations/inheritance_spec.rb +5 -7
- data/spec/integration/relations/reading_spec.rb +32 -65
- data/spec/integration/relations/registry_dsl_spec.rb +5 -4
- data/spec/integration/repositories/extending_relations_spec.rb +6 -7
- data/spec/integration/repositories/setting_logger_spec.rb +5 -7
- data/spec/integration/setup_spec.rb +49 -61
- data/spec/shared/command_graph.rb +50 -0
- data/spec/shared/container.rb +9 -0
- data/spec/shared/gateway_only.rb +6 -0
- data/spec/shared/no_container.rb +16 -0
- data/spec/shared/one_behavior.rb +4 -4
- data/spec/shared/users_and_tasks.rb +5 -17
- data/spec/spec_helper.rb +5 -3
- data/spec/test/memory_repository_lint_test.rb +1 -1
- data/spec/unit/rom/auto_registration_spec.rb +54 -0
- data/spec/unit/rom/commands/graph_spec.rb +18 -44
- data/spec/unit/rom/commands/lazy_spec.rb +246 -35
- data/spec/unit/rom/commands/result_spec.rb +56 -0
- data/spec/unit/rom/commands_spec.rb +9 -73
- data/spec/unit/rom/configurable_spec.rb +49 -0
- data/spec/unit/rom/configuration_spec.rb +61 -0
- data/spec/unit/rom/container_spec.rb +39 -33
- data/spec/unit/rom/create_container_spec.rb +151 -0
- data/spec/unit/rom/environment_spec.rb +123 -0
- data/spec/unit/rom/gateway_spec.rb +58 -2
- data/spec/unit/rom/global_spec.rb +10 -7
- data/spec/unit/rom/plugin_spec.rb +44 -25
- data/spec/unit/rom/plugins/relation/key_inference_spec.rb +27 -0
- data/spec/unit/rom/plugins/relation/view_spec.rb +47 -0
- data/spec/unit/rom/relation/composite_spec.rb +20 -20
- data/spec/unit/rom/relation/curried_spec.rb +10 -11
- data/spec/unit/rom/relation/graph_spec.rb +27 -27
- data/spec/unit/rom/relation/lazy/combine_spec.rb +26 -20
- data/spec/unit/rom/relation/lazy_spec.rb +38 -38
- data/spec/unit/rom/relation/loaded_spec.rb +2 -3
- data/spec/unit/rom/relation_spec.rb +39 -2
- metadata +58 -66
- data/lib/rom/commands/abstract.rb +0 -184
- data/lib/rom/environment_plugin.rb +0 -17
- data/lib/rom/environment_plugins/auto_registration.rb +0 -38
- data/lib/rom/repository.rb +0 -16
- data/lib/rom/setup_dsl/command.rb +0 -36
- data/lib/rom/setup_dsl/mapper.rb +0 -32
- data/lib/rom/setup_dsl/relation.rb +0 -30
- data/spec/integration/inline_setup_spec.rb +0 -65
- data/spec/unit/rom/repository_spec.rb +0 -12
- data/spec/unit/rom/setup_spec.rb +0 -253
@@ -0,0 +1,115 @@
|
|
1
|
+
module ROM
|
2
|
+
# Base command class with factory class-level interface and setup-related logic
|
3
|
+
#
|
4
|
+
# @private
|
5
|
+
class Command
|
6
|
+
module ClassInterface
|
7
|
+
# Return adapter specific sub-class based on the adapter identifier
|
8
|
+
#
|
9
|
+
# This is a syntax sugar to make things consistent
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# ROM::Commands::Create[:memory]
|
13
|
+
# # => ROM::Memory::Commands::Create
|
14
|
+
#
|
15
|
+
# @param [Symbol] adapter identifier
|
16
|
+
#
|
17
|
+
# @return [Class]
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
def [](adapter)
|
21
|
+
adapter_namespace(adapter).const_get(Inflector.demodulize(name))
|
22
|
+
end
|
23
|
+
|
24
|
+
# Return namespaces that contains command subclasses of a specific adapter
|
25
|
+
#
|
26
|
+
# @param [Symbol] adapter identifier
|
27
|
+
#
|
28
|
+
# @return [Module]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
def adapter_namespace(adapter)
|
32
|
+
ROM.adapters.fetch(adapter).const_get(:Commands)
|
33
|
+
rescue KeyError
|
34
|
+
raise AdapterNotPresentError.new(adapter, :relation)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Build a command class for a specific relation with options
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# class CreateUser < ROM::Commands::Create[:memory]
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# command = CreateUser.build(rom.relations[:users])
|
44
|
+
#
|
45
|
+
# @param [Relation] relation
|
46
|
+
# @param [Hash] options
|
47
|
+
#
|
48
|
+
# @return [Command]
|
49
|
+
#
|
50
|
+
# @api public
|
51
|
+
def build(relation, options = EMPTY_HASH)
|
52
|
+
new(relation, self.options.merge(options))
|
53
|
+
end
|
54
|
+
|
55
|
+
# Use a configured plugin in this relation
|
56
|
+
#
|
57
|
+
# @example
|
58
|
+
# class CreateUser < ROM::Commands::Create[:memory]
|
59
|
+
# use :pagintion
|
60
|
+
#
|
61
|
+
# per_page 30
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# @param [Symbol] plugin
|
65
|
+
# @param [Hash] options
|
66
|
+
# @option options [Symbol] :adapter (:default) first adapter to check for plugin
|
67
|
+
#
|
68
|
+
# @api public
|
69
|
+
def use(plugin, _options = EMPTY_HASH)
|
70
|
+
ROM.plugin_registry.commands.fetch(plugin, adapter).apply_to(self)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @api private
|
74
|
+
def relation_methods_mod(relation_class)
|
75
|
+
mod = Module.new
|
76
|
+
|
77
|
+
relation_class.view_methods.each do |meth|
|
78
|
+
mod.module_eval <<-RUBY
|
79
|
+
def #{meth}(*args)
|
80
|
+
response = relation.public_send(:#{meth}, *args)
|
81
|
+
|
82
|
+
if response.is_a?(relation.class)
|
83
|
+
new(response)
|
84
|
+
else
|
85
|
+
response
|
86
|
+
end
|
87
|
+
end
|
88
|
+
RUBY
|
89
|
+
end
|
90
|
+
|
91
|
+
mod
|
92
|
+
end
|
93
|
+
|
94
|
+
# Return default name of the command class based on its name
|
95
|
+
#
|
96
|
+
# During setup phase this is used by defalut as `register_as` option
|
97
|
+
#
|
98
|
+
# @return [Symbol]
|
99
|
+
#
|
100
|
+
# @api private
|
101
|
+
def default_name
|
102
|
+
Inflector.underscore(Inflector.demodulize(name)).to_sym
|
103
|
+
end
|
104
|
+
|
105
|
+
# Return default options based on class macros
|
106
|
+
#
|
107
|
+
# @return [Hash]
|
108
|
+
#
|
109
|
+
# @api private
|
110
|
+
def options
|
111
|
+
{ input: input, validator: validator, result: result }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/rom/commands/graph.rb
CHANGED
@@ -8,6 +8,8 @@ module ROM
|
|
8
8
|
#
|
9
9
|
# @api private
|
10
10
|
class Graph
|
11
|
+
include Dry::Equalizer(:root, :nodes)
|
12
|
+
|
11
13
|
extend ClassInterface
|
12
14
|
|
13
15
|
include Options
|
@@ -50,35 +52,27 @@ module ROM
|
|
50
52
|
#
|
51
53
|
# @api public
|
52
54
|
def call(*args)
|
53
|
-
|
54
|
-
left = root.call(*args)
|
55
|
-
|
56
|
-
right = nodes.map do |node|
|
57
|
-
begin
|
58
|
-
response =
|
59
|
-
if node.lazy?
|
60
|
-
node.call(args.first, left)
|
61
|
-
else
|
62
|
-
node.call(left)
|
63
|
-
end
|
64
|
-
rescue => err
|
65
|
-
raise CommandFailure.new(node, err)
|
66
|
-
end
|
55
|
+
left = root.call(*args)
|
67
56
|
|
68
|
-
|
69
|
-
|
57
|
+
right = nodes.map { |node|
|
58
|
+
response =
|
59
|
+
if node.lazy?
|
60
|
+
node.call(args.first, left)
|
70
61
|
else
|
71
|
-
|
62
|
+
node.call(left)
|
72
63
|
end
|
73
|
-
end
|
74
64
|
|
75
|
-
if one?
|
76
|
-
[
|
65
|
+
if node.one? && !node.graph?
|
66
|
+
[response]
|
77
67
|
else
|
78
|
-
|
68
|
+
response
|
79
69
|
end
|
80
|
-
|
81
|
-
|
70
|
+
}
|
71
|
+
|
72
|
+
if one?
|
73
|
+
[[left], right]
|
74
|
+
else
|
75
|
+
[left, right]
|
82
76
|
end
|
83
77
|
end
|
84
78
|
|
@@ -0,0 +1,176 @@
|
|
1
|
+
module ROM
|
2
|
+
module Commands
|
3
|
+
class Graph
|
4
|
+
# Command graph builder DSL
|
5
|
+
#
|
6
|
+
# @api public
|
7
|
+
class Builder
|
8
|
+
# @api private
|
9
|
+
UnspecifiedRelationError = Class.new(StandardError)
|
10
|
+
DoubleRestrictionError = Class.new(StandardError)
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
class Node
|
14
|
+
# @api private
|
15
|
+
Restriction = Struct.new(:relation, :proc)
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
Command = Struct.new(:name, :relation, :key, :proc)
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
def initialize
|
22
|
+
@nodes = []
|
23
|
+
end
|
24
|
+
|
25
|
+
# @api public
|
26
|
+
def to_ast
|
27
|
+
[]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Any missing method called on this is treated as a ROM command
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
def method_missing(*args, &block)
|
34
|
+
command(*args, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @api public
|
38
|
+
def command(name, relation = nil, key = nil, proc = nil, &block)
|
39
|
+
if relation.is_a?(Hash)
|
40
|
+
key, relation = relation.to_a.first
|
41
|
+
end
|
42
|
+
|
43
|
+
raise UnspecifiedRelationError if relation.nil?
|
44
|
+
|
45
|
+
if relation.is_a?(RestrictionNode)
|
46
|
+
RestrictionNode.new(relation.restriction).command(name, from: key, &block)
|
47
|
+
else
|
48
|
+
key ||= relation
|
49
|
+
|
50
|
+
command = Command.new(name, relation, key, proc)
|
51
|
+
node = CommandNode.new(command)
|
52
|
+
block.call(node) if block
|
53
|
+
node
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# @api public
|
58
|
+
def restrict(name, &block)
|
59
|
+
RestrictionNode.new(Restriction.new(name, block), self)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api private
|
64
|
+
class CommandNode < Node
|
65
|
+
# @api private
|
66
|
+
def initialize(command = nil)
|
67
|
+
@command = command
|
68
|
+
@nodes = []
|
69
|
+
end
|
70
|
+
|
71
|
+
# Tiny bit of synctactic sugar
|
72
|
+
#
|
73
|
+
# @api public
|
74
|
+
def each(&block)
|
75
|
+
block.call(self)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Return command ast from this union node
|
79
|
+
#
|
80
|
+
# @return [Array]
|
81
|
+
#
|
82
|
+
# @api private
|
83
|
+
def to_ast
|
84
|
+
if @command.proc
|
85
|
+
command = [@command.name => @command.proc]
|
86
|
+
else
|
87
|
+
command = [@command.name]
|
88
|
+
end
|
89
|
+
|
90
|
+
key_relation_map = { @command.key => @command.relation }
|
91
|
+
|
92
|
+
command << @nodes.map(&:to_ast) unless @nodes.empty?
|
93
|
+
|
94
|
+
[key_relation_map, command]
|
95
|
+
end
|
96
|
+
|
97
|
+
# @api public
|
98
|
+
def command(*args, &block)
|
99
|
+
node = super
|
100
|
+
@nodes << node
|
101
|
+
node
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# @api private
|
106
|
+
class RestrictionNode < Node
|
107
|
+
attr_reader :restriction
|
108
|
+
|
109
|
+
def initialize(restriction, parent_node = nil)
|
110
|
+
super()
|
111
|
+
@restriction = restriction
|
112
|
+
@parent_node = parent_node
|
113
|
+
end
|
114
|
+
|
115
|
+
# @api public
|
116
|
+
def command(name, options = {}, &block)
|
117
|
+
relation = @restriction.relation
|
118
|
+
key = options[:from] || relation
|
119
|
+
proc = @restriction.proc
|
120
|
+
|
121
|
+
if @parent_node
|
122
|
+
@parent_node.command(name, relation, key, proc, &block)
|
123
|
+
else
|
124
|
+
super(name, relation, key, proc, &block)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# @api private
|
129
|
+
def restrict(*args, &block)
|
130
|
+
raise DoubleRestrictionError
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# @api private
|
135
|
+
class RootNode < Node
|
136
|
+
def to_ast
|
137
|
+
if @nodes.size > 0
|
138
|
+
@nodes.first.to_ast
|
139
|
+
else
|
140
|
+
[]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def command(*args, &block)
|
145
|
+
node = super
|
146
|
+
@nodes << node
|
147
|
+
node
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# @api private
|
152
|
+
class BuilderNode < RootNode
|
153
|
+
def initialize(container)
|
154
|
+
super()
|
155
|
+
@container = container
|
156
|
+
end
|
157
|
+
|
158
|
+
def command(*args, &block)
|
159
|
+
super
|
160
|
+
@container.command(to_ast)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# @api public
|
165
|
+
def initialize(container)
|
166
|
+
@container = container
|
167
|
+
end
|
168
|
+
|
169
|
+
# @api private
|
170
|
+
def method_missing(*args, &block)
|
171
|
+
BuilderNode.new(@container).send(*args, &block)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -24,7 +24,7 @@ module ROM
|
|
24
24
|
|
25
25
|
# @api private
|
26
26
|
def build_command(registry, spec, other, path)
|
27
|
-
|
27
|
+
cmd_opts, nodes = other
|
28
28
|
|
29
29
|
key, relation =
|
30
30
|
if spec.is_a?(Hash)
|
@@ -33,12 +33,18 @@ module ROM
|
|
33
33
|
[spec, spec]
|
34
34
|
end
|
35
35
|
|
36
|
+
name, opts =
|
37
|
+
if cmd_opts.is_a?(Hash)
|
38
|
+
cmd_opts.to_a.first
|
39
|
+
else
|
40
|
+
[cmd_opts]
|
41
|
+
end
|
36
42
|
|
37
43
|
command = registry[relation][name]
|
38
44
|
tuple_path = Array[*path] << key
|
39
45
|
input_proc = InputEvaluator.build(tuple_path, nodes)
|
40
46
|
|
41
|
-
command = command.with(input_proc)
|
47
|
+
command = command.with(input_proc, opts)
|
42
48
|
|
43
49
|
if nodes
|
44
50
|
if nodes.all? { |node| node.is_a?(Array) }
|
@@ -2,6 +2,8 @@ module ROM
|
|
2
2
|
module Commands
|
3
3
|
class Graph
|
4
4
|
class InputEvaluator
|
5
|
+
include Dry::Equalizer(:tuple_path, :excluded_keys)
|
6
|
+
|
5
7
|
attr_reader :tuple_path
|
6
8
|
|
7
9
|
attr_reader :excluded_keys
|
@@ -35,21 +37,23 @@ module ROM
|
|
35
37
|
def call(*args)
|
36
38
|
input, index = args
|
37
39
|
|
38
|
-
|
39
|
-
|
40
|
+
value =
|
41
|
+
begin
|
40
42
|
if index
|
41
43
|
tuple_path[0..tuple_path.size-2]
|
42
|
-
.reduce(input) { |a,e| a.fetch(e) }
|
44
|
+
.reduce(input) { |a, e| a.fetch(e) }
|
43
45
|
.at(index)[tuple_path.last]
|
44
46
|
else
|
45
|
-
tuple_path.reduce(input) { |a,e| a.fetch(e) }
|
47
|
+
tuple_path.reduce(input) { |a, e| a.fetch(e) }
|
46
48
|
end
|
47
|
-
|
48
|
-
|
49
|
-
value.is_a?(Array) ? value.map(&exclude_proc) : exclude_proc[value]
|
50
|
-
else
|
51
|
-
value
|
49
|
+
rescue KeyError => e
|
50
|
+
raise KeyMissing, e.message
|
52
51
|
end
|
52
|
+
|
53
|
+
if excluded_keys
|
54
|
+
value.is_a?(Array) ? value.map(&exclude_proc) : exclude_proc[value]
|
55
|
+
else
|
56
|
+
value
|
53
57
|
end
|
54
58
|
end
|
55
59
|
end
|
data/lib/rom/commands/lazy.rb
CHANGED
@@ -7,16 +7,32 @@ module ROM
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
class Lazy
|
10
|
+
include Dry::Equalizer(:command, :evaluator)
|
11
|
+
|
10
12
|
# @attr_reader [Command] command The wrapped command
|
11
13
|
attr_reader :command
|
12
14
|
|
13
15
|
# @attr_reader [Proc] evaluator The proc that will evaluate the input
|
14
16
|
attr_reader :evaluator
|
15
17
|
|
18
|
+
attr_reader :command_proc
|
19
|
+
|
16
20
|
# @api private
|
17
|
-
def
|
21
|
+
def self.[](command)
|
22
|
+
case command
|
23
|
+
when Commands::Create then Lazy::Create
|
24
|
+
when Commands::Update then Lazy::Update
|
25
|
+
when Commands::Delete then Lazy::Delete
|
26
|
+
else
|
27
|
+
self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @api private
|
32
|
+
def initialize(command, evaluator, command_proc = nil)
|
18
33
|
@command = command
|
19
34
|
@evaluator = evaluator
|
35
|
+
@command_proc = command_proc || proc { |*| command }
|
20
36
|
end
|
21
37
|
|
22
38
|
# Evaluate command's input using the input proc and pass to command
|
@@ -25,21 +41,7 @@ module ROM
|
|
25
41
|
#
|
26
42
|
# @api public
|
27
43
|
def call(*args)
|
28
|
-
|
29
|
-
last = args.last
|
30
|
-
size = args.size
|
31
|
-
|
32
|
-
if size > 1 && last.is_a?(Array)
|
33
|
-
last.map.with_index do |item, index|
|
34
|
-
input = evaluator.call(first, index)
|
35
|
-
command.call(input, item)
|
36
|
-
end.reduce(:concat)
|
37
|
-
else
|
38
|
-
input = evaluator.call(first)
|
39
|
-
command.call(input, *args[1..size-1])
|
40
|
-
end
|
41
|
-
rescue => err
|
42
|
-
raise CommandFailure.new(command, err)
|
44
|
+
raise NotImplementedError
|
43
45
|
end
|
44
46
|
|
45
47
|
# Compose a lazy command with another one
|
@@ -78,7 +80,7 @@ module ROM
|
|
78
80
|
response = command.public_send(name, *args, &block)
|
79
81
|
|
80
82
|
if response.instance_of?(command.class)
|
81
|
-
self.class.new(response, evaluator)
|
83
|
+
self.class.new(response, evaluator, command_proc)
|
82
84
|
else
|
83
85
|
response
|
84
86
|
end
|
@@ -89,3 +91,7 @@ module ROM
|
|
89
91
|
end
|
90
92
|
end
|
91
93
|
end
|
94
|
+
|
95
|
+
require 'rom/commands/lazy/create'
|
96
|
+
require 'rom/commands/lazy/update'
|
97
|
+
require 'rom/commands/lazy/delete'
|