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.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +30 -12
  3. data/.travis.yml +1 -1
  4. data/CHANGELOG.md +24 -0
  5. data/Gemfile +7 -3
  6. data/README.md +24 -11
  7. data/lib/rom.rb +9 -26
  8. data/lib/rom/command.rb +113 -75
  9. data/lib/rom/commands/class_interface.rb +115 -0
  10. data/lib/rom/commands/graph.rb +17 -23
  11. data/lib/rom/commands/graph/builder.rb +176 -0
  12. data/lib/rom/commands/graph/class_interface.rb +8 -2
  13. data/lib/rom/commands/graph/input_evaluator.rb +13 -9
  14. data/lib/rom/commands/lazy.rb +23 -17
  15. data/lib/rom/commands/lazy/create.rb +23 -0
  16. data/lib/rom/commands/lazy/delete.rb +27 -0
  17. data/lib/rom/commands/lazy/update.rb +34 -0
  18. data/lib/rom/commands/result.rb +14 -0
  19. data/lib/rom/commands/update.rb +0 -4
  20. data/lib/rom/configuration.rb +86 -0
  21. data/lib/rom/{setup_dsl/setup.rb → configuration_dsl.rb} +9 -7
  22. data/lib/rom/configuration_dsl/command.rb +43 -0
  23. data/lib/rom/{setup_dsl → configuration_dsl}/command_dsl.rb +5 -4
  24. data/lib/rom/configuration_dsl/mapper.rb +37 -0
  25. data/lib/rom/{setup_dsl → configuration_dsl}/mapper_dsl.rb +11 -5
  26. data/lib/rom/configuration_dsl/relation.rb +26 -0
  27. data/lib/rom/configuration_plugin.rb +17 -0
  28. data/lib/rom/constants.rb +5 -12
  29. data/lib/rom/container.rb +11 -8
  30. data/lib/rom/create_container.rb +61 -0
  31. data/lib/rom/environment.rb +27 -241
  32. data/lib/rom/gateway.rb +18 -2
  33. data/lib/rom/global.rb +24 -0
  34. data/lib/rom/global/plugin_dsl.rb +2 -0
  35. data/lib/rom/lint/spec.rb +0 -12
  36. data/lib/rom/lint/test.rb +0 -31
  37. data/lib/rom/memory/commands.rb +2 -2
  38. data/lib/rom/memory/gateway.rb +2 -0
  39. data/lib/rom/pipeline.rb +1 -1
  40. data/lib/rom/plugin_base.rb +1 -1
  41. data/lib/rom/plugin_registry.rb +12 -10
  42. data/lib/rom/plugins/configuration/configuration_dsl.rb +16 -0
  43. data/lib/rom/plugins/relation/key_inference.rb +31 -0
  44. data/lib/rom/plugins/relation/view.rb +90 -0
  45. data/lib/rom/plugins/relation/view/dsl.rb +32 -0
  46. data/lib/rom/relation.rb +1 -11
  47. data/lib/rom/relation/class_interface.rb +37 -50
  48. data/lib/rom/setup.rb +13 -104
  49. data/lib/rom/setup/auto_registration.rb +55 -0
  50. data/lib/rom/setup/finalize.rb +113 -127
  51. data/lib/rom/setup/finalize/commands.rb +67 -0
  52. data/lib/rom/setup/finalize/mappers.rb +36 -0
  53. data/lib/rom/setup/finalize/relations.rb +53 -0
  54. data/lib/rom/support/configurable.rb +21 -7
  55. data/lib/rom/version.rb +1 -1
  56. data/rakelib/mutant.rake +4 -1
  57. data/rom.gemspec +3 -4
  58. data/spec/fixtures/app/commands/create_user.rb +2 -0
  59. data/spec/fixtures/app/mappers/user_list.rb +2 -0
  60. data/spec/fixtures/app/relations/users.rb +2 -0
  61. data/spec/fixtures/lib/persistence/commands/create_user.rb +6 -0
  62. data/spec/fixtures/lib/persistence/mappers/user_list.rb +6 -0
  63. data/spec/fixtures/lib/persistence/relations/users.rb +6 -0
  64. data/spec/{unit/rom → integration}/command_registry_spec.rb +8 -9
  65. data/spec/integration/commands/create_spec.rb +17 -13
  66. data/spec/integration/commands/delete_spec.rb +12 -11
  67. data/spec/integration/commands/error_handling_spec.rb +5 -4
  68. data/spec/integration/commands/graph_builder_spec.rb +213 -0
  69. data/spec/integration/commands/graph_spec.rb +112 -49
  70. data/spec/integration/commands/update_spec.rb +14 -11
  71. data/spec/integration/commands_spec.rb +60 -0
  72. data/spec/integration/mappers/combine_spec.rb +7 -6
  73. data/spec/integration/mappers/deep_embedded_spec.rb +5 -6
  74. data/spec/integration/mappers/definition_dsl_spec.rb +19 -18
  75. data/spec/integration/mappers/embedded_spec.rb +11 -12
  76. data/spec/integration/mappers/exclude_spec.rb +5 -6
  77. data/spec/integration/mappers/fold_spec.rb +8 -7
  78. data/spec/integration/mappers/group_spec.rb +16 -15
  79. data/spec/integration/mappers/overwrite_attributes_value_spec.rb +5 -5
  80. data/spec/integration/mappers/prefix_separator_spec.rb +5 -7
  81. data/spec/integration/mappers/prefix_spec.rb +5 -7
  82. data/spec/integration/mappers/prefixing_attributes_spec.rb +7 -7
  83. data/spec/integration/mappers/registering_custom_mappers_spec.rb +4 -5
  84. data/spec/integration/mappers/renaming_attributes_spec.rb +18 -18
  85. data/spec/integration/mappers/step_spec.rb +11 -12
  86. data/spec/integration/mappers/symbolizing_attributes_spec.rb +11 -8
  87. data/spec/integration/mappers/unfold_spec.rb +9 -10
  88. data/spec/integration/mappers/ungroup_spec.rb +10 -11
  89. data/spec/integration/mappers/unwrap_spec.rb +10 -15
  90. data/spec/integration/mappers/wrap_spec.rb +16 -15
  91. data/spec/{unit/rom → integration}/memory/commands/create_spec.rb +7 -5
  92. data/spec/{unit/rom → integration}/memory/commands/delete_spec.rb +7 -5
  93. data/spec/{unit/rom → integration}/memory/commands/update_spec.rb +7 -5
  94. data/spec/integration/multi_env_spec.rb +16 -124
  95. data/spec/integration/multi_repo_spec.rb +9 -9
  96. data/spec/integration/relations/default_dataset_spec.rb +15 -0
  97. data/spec/integration/relations/inheritance_spec.rb +5 -7
  98. data/spec/integration/relations/reading_spec.rb +32 -65
  99. data/spec/integration/relations/registry_dsl_spec.rb +5 -4
  100. data/spec/integration/repositories/extending_relations_spec.rb +6 -7
  101. data/spec/integration/repositories/setting_logger_spec.rb +5 -7
  102. data/spec/integration/setup_spec.rb +49 -61
  103. data/spec/shared/command_graph.rb +50 -0
  104. data/spec/shared/container.rb +9 -0
  105. data/spec/shared/gateway_only.rb +6 -0
  106. data/spec/shared/no_container.rb +16 -0
  107. data/spec/shared/one_behavior.rb +4 -4
  108. data/spec/shared/users_and_tasks.rb +5 -17
  109. data/spec/spec_helper.rb +5 -3
  110. data/spec/test/memory_repository_lint_test.rb +1 -1
  111. data/spec/unit/rom/auto_registration_spec.rb +54 -0
  112. data/spec/unit/rom/commands/graph_spec.rb +18 -44
  113. data/spec/unit/rom/commands/lazy_spec.rb +246 -35
  114. data/spec/unit/rom/commands/result_spec.rb +56 -0
  115. data/spec/unit/rom/commands_spec.rb +9 -73
  116. data/spec/unit/rom/configurable_spec.rb +49 -0
  117. data/spec/unit/rom/configuration_spec.rb +61 -0
  118. data/spec/unit/rom/container_spec.rb +39 -33
  119. data/spec/unit/rom/create_container_spec.rb +151 -0
  120. data/spec/unit/rom/environment_spec.rb +123 -0
  121. data/spec/unit/rom/gateway_spec.rb +58 -2
  122. data/spec/unit/rom/global_spec.rb +10 -7
  123. data/spec/unit/rom/plugin_spec.rb +44 -25
  124. data/spec/unit/rom/plugins/relation/key_inference_spec.rb +27 -0
  125. data/spec/unit/rom/plugins/relation/view_spec.rb +47 -0
  126. data/spec/unit/rom/relation/composite_spec.rb +20 -20
  127. data/spec/unit/rom/relation/curried_spec.rb +10 -11
  128. data/spec/unit/rom/relation/graph_spec.rb +27 -27
  129. data/spec/unit/rom/relation/lazy/combine_spec.rb +26 -20
  130. data/spec/unit/rom/relation/lazy_spec.rb +38 -38
  131. data/spec/unit/rom/relation/loaded_spec.rb +2 -3
  132. data/spec/unit/rom/relation_spec.rb +39 -2
  133. metadata +58 -66
  134. data/lib/rom/commands/abstract.rb +0 -184
  135. data/lib/rom/environment_plugin.rb +0 -17
  136. data/lib/rom/environment_plugins/auto_registration.rb +0 -38
  137. data/lib/rom/repository.rb +0 -16
  138. data/lib/rom/setup_dsl/command.rb +0 -36
  139. data/lib/rom/setup_dsl/mapper.rb +0 -32
  140. data/lib/rom/setup_dsl/relation.rb +0 -30
  141. data/spec/integration/inline_setup_spec.rb +0 -65
  142. data/spec/unit/rom/repository_spec.rb +0 -12
  143. data/spec/unit/rom/setup_spec.rb +0 -253
@@ -21,7 +21,7 @@ class MemoryDatasetLintTest < Minitest::Test
21
21
  include ROM::Lint::TestEnumerableDataset
22
22
 
23
23
  def setup
24
- @data = [{ name: 'Jane', age: 24 }, { name: 'Joe', age: 25 }]
24
+ @data = [{ name: 'Jane', age: 24 }, { name: 'Joe', age: 25 }]
25
25
  @dataset = ROM::Memory::Dataset.new(@data)
26
26
  end
27
27
  end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'rom/setup/auto_registration'
3
+
4
+ RSpec.describe ROM::Setup, '#auto_registration' do
5
+ let(:setup) { ROM::Setup.new }
6
+
7
+ context 'with namespace turned on' do
8
+ before do
9
+ setup.auto_registration(SPEC_ROOT.join('fixtures/lib/persistence'))
10
+ end
11
+
12
+ describe '#relations' do
13
+ it 'loads files and returns constants' do
14
+ expect(setup.relation_classes).to eql([Persistence::Relations::Users])
15
+ end
16
+ end
17
+
18
+ describe '#commands' do
19
+ it 'loads files and returns constants' do
20
+ expect(setup.command_classes).to eql([Persistence::Commands::CreateUser])
21
+ end
22
+ end
23
+
24
+ describe '#mappers' do
25
+ it 'loads files and returns constants' do
26
+ expect(setup.mapper_classes).to eql([Persistence::Mappers::UserList])
27
+ end
28
+ end
29
+ end
30
+
31
+ context 'with namespace turned off' do
32
+ before do
33
+ setup.auto_registration(SPEC_ROOT.join('fixtures/app'), namespace: false)
34
+ end
35
+
36
+ describe '#relations' do
37
+ it 'loads files and returns constants' do
38
+ expect(setup.relation_classes).to eql([Users])
39
+ end
40
+ end
41
+
42
+ describe '#commands' do
43
+ it 'loads files and returns constants' do
44
+ expect(setup.command_classes).to eql([CreateUser])
45
+ end
46
+ end
47
+
48
+ describe '#mappers' do
49
+ it 'loads files and returns constants' do
50
+ expect(setup.mapper_classes).to eql([UserList])
51
+ end
52
+ end
53
+ end
54
+ end
@@ -6,7 +6,7 @@ describe ROM::Commands::Graph do
6
6
  expect(command.call).to match_array([
7
7
  # parent users
8
8
  [
9
- { name: 'Jane' },
9
+ { name: 'Jane' }
10
10
  ],
11
11
  [
12
12
  [
@@ -31,15 +31,15 @@ describe ROM::Commands::Graph do
31
31
  before { command.call }
32
32
 
33
33
  it 'inserts root' do
34
- expect(rom.relation(:users)).to match_array([{ name: 'Jane' }])
34
+ expect(container.relation(:users)).to match_array([{ name: 'Jane' }])
35
35
  end
36
36
 
37
37
  it 'inserts root nodes' do
38
- expect(rom.relation(:tasks)).to match_array([{ user: 'Jane', title: 'One' }])
38
+ expect(container.relation(:tasks)).to match_array([{ user: 'Jane', title: 'One' }])
39
39
  end
40
40
 
41
41
  it 'inserts nested graph nodes' do
42
- expect(rom.relation(:tags)).to match_array([
42
+ expect(container.relation(:tags)).to match_array([
43
43
  { name: 'red', task: 'One' },
44
44
  { name: 'green', task: 'One' },
45
45
  { name: 'blue', task: 'One' }
@@ -48,31 +48,30 @@ describe ROM::Commands::Graph do
48
48
  end
49
49
  end
50
50
 
51
- let(:rom) { setup.finalize }
52
- let(:setup) { ROM.setup(:memory) }
51
+ include_context 'container'
53
52
 
54
- let(:create_user) { rom.command(:users).create }
55
- let(:create_task) { rom.command(:tasks).create }
53
+ let(:create_user) { container.command(:users).create }
54
+ let(:create_task) { container.command(:tasks).create }
56
55
 
57
- let(:create_many_tasks) { rom.command(:tasks).create_many }
58
- let(:create_many_tags) { rom.command(:tags).create_many }
56
+ let(:create_many_tasks) { container.command(:tasks).create_many }
57
+ let(:create_many_tags) { container.command(:tags).create_many }
59
58
 
60
59
  let(:user) { { name: 'Jane' } }
61
60
  let(:task) { { title: 'One' } }
62
61
  let(:tags) { [{ name: 'red' }, { name: 'green' }, { name: 'blue' }] }
63
62
 
64
63
  before do
65
- setup.relation(:users)
66
- setup.relation(:tasks)
67
- setup.relation(:tags)
64
+ configuration.relation(:users)
65
+ configuration.relation(:tasks)
66
+ configuration.relation(:tags)
68
67
 
69
- setup.commands(:users) do
68
+ configuration.commands(:users) do
70
69
  define(:create) do
71
70
  result :one
72
71
  end
73
72
  end
74
73
 
75
- setup.commands(:tasks) do
74
+ configuration.commands(:tasks) do
76
75
  define(:create) do
77
76
  result :one
78
77
 
@@ -90,7 +89,7 @@ describe ROM::Commands::Graph do
90
89
  end
91
90
  end
92
91
 
93
- setup.commands(:tags) do
92
+ configuration.commands(:tags) do
94
93
  define(:create) do
95
94
  register_as :create_many
96
95
 
@@ -125,37 +124,11 @@ describe ROM::Commands::Graph do
125
124
  end
126
125
  end
127
126
  end
128
-
129
- context 'when error is raised' do
130
- subject(:command) do
131
- create_user.with(user).combine(create_many_tasks.with([task]))
132
- end
133
-
134
- it 're-raises the error providing proper context when root fails' do
135
- allow(command.root).to receive(:call).and_raise(StandardError, 'ooops')
136
-
137
- expect { command.call }.to raise_error(ROM::CommandFailure, /oops/)
138
- end
139
-
140
- it 're-raises the error providing proper context when a node fails' do
141
- allow(command.nodes[0]).to receive(:call).and_raise(StandardError, 'ooops')
142
-
143
- expect { command.call }.to raise_error(ROM::CommandFailure, /oops/)
144
-
145
- begin
146
- command.call
147
- rescue ROM::CommandFailure => e
148
- expect(e.original_error).to be_a(ROM::CommandFailure)
149
- expect(e.original_error.message).to include('ooops')
150
- expect(e.backtrace).to eql(e.original_error.backtrace)
151
- end
152
- end
153
- end
154
127
  end
155
128
 
156
129
  describe 'pipeline' do
157
130
  subject(:command) do
158
- rom.command(:users).as(:entity).create.with(user)
131
+ container.command(:users).as(:entity).create.with(user)
159
132
  .combine(create_task.with(task)
160
133
  .combine(create_many_tags.with(tags)))
161
134
  end
@@ -185,6 +158,7 @@ describe ROM::Commands::Graph do
185
158
  end
186
159
  end
187
160
  end
161
+ configuration.register_mapper(Test::UserMapper)
188
162
  end
189
163
 
190
164
  it 'sends data through the pipeline' do
@@ -196,7 +170,7 @@ describe ROM::Commands::Graph do
196
170
  tags: [
197
171
  Test::Tag.new(name: 'red'),
198
172
  Test::Tag.new(name: 'green'),
199
- Test::Tag.new(name: 'blue'),
173
+ Test::Tag.new(name: 'blue')
200
174
  ]
201
175
  )
202
176
  )
@@ -1,52 +1,275 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ROM::Commands::Lazy do
4
- let(:rom) { setup.finalize }
5
- let(:setup) { ROM.setup(:memory) }
4
+ include_context 'container'
6
5
 
7
- let(:create_user) { rom.command(:users).create }
8
- let(:update_user) { rom.command(:users).update }
9
- let(:create_task) { rom.command(:tasks).create }
6
+ let(:create_user) { container.command(:users).create }
7
+ let(:update_user) { container.command(:users).update }
8
+ let(:delete_user) { container.command(:users).delete }
10
9
 
11
- let(:user) { { user: { name: 'Jane' } } }
10
+ let(:create_task) { container.command(:tasks).create }
11
+ let(:create_tasks) { container.command(:tasks).create_many }
12
+ let(:update_task) { container.command(:tasks).update }
13
+
14
+ let(:input) { { user: { name: 'Jane', email: 'jane@doe.org' } } }
15
+ let(:jane) { input[:user] }
12
16
  let(:evaluator) { -> input { input[:user] } }
13
17
 
14
18
  before do
15
- setup.relation(:tasks)
19
+ configuration.relation(:tasks) do
20
+ def by_user_and_title(user, title)
21
+ by_user(user).by_title(title)
22
+ end
23
+
24
+ def by_user(user)
25
+ restrict(user: user)
26
+ end
16
27
 
17
- setup.relation(:users) do
28
+ def by_title(title)
29
+ restrict(title: title)
30
+ end
31
+ end
32
+
33
+ configuration.relation(:users) do
18
34
  def by_name(name)
19
35
  restrict(name: name)
20
36
  end
21
37
  end
22
38
 
23
- setup.commands(:users) do
39
+ configuration.commands(:users) do
24
40
  define(:create) do
25
41
  result :one
26
42
  end
27
43
 
28
- define(:update)
44
+ define(:update) do
45
+ result :one
46
+ end
47
+
48
+ define(:delete) do
49
+ result :one
50
+ end
29
51
  end
30
52
 
31
- setup.commands(:tasks) do
32
- define(:create)
53
+ configuration.commands(:tasks) do
54
+ define(:create) do
55
+ result :one
56
+ end
57
+
58
+ define(:create_many, type: :create) do
59
+ def execute(tuples, user)
60
+ super(tuples.map { |tuple| tuple.merge(user: user[:name]) })
61
+ end
62
+ end
63
+
64
+ define(:update) do
65
+ result :one
66
+
67
+ def execute(tuple, user)
68
+ super(tuple.merge(user: user[:name]))
69
+ end
70
+ end
33
71
  end
34
72
  end
35
73
 
36
74
  describe '#call' do
37
- subject(:command) { ROM::Commands::Lazy.new(create_user, evaluator) }
75
+ context 'with a create command' do
76
+ subject(:command) { ROM::Commands::Lazy[create_user].new(create_user, evaluator) }
77
+
78
+ it 'evaluates the input and calls command' do
79
+ command.call(input)
80
+
81
+ expect(container.relation(:users)).to match_array([jane])
82
+ end
83
+ end
84
+
85
+ context 'with a create command for many child tuples' do
86
+ subject(:command) do
87
+ ROM::Commands::Lazy[create_tasks].new(create_tasks, evaluator)
88
+ end
89
+
90
+ let(:evaluator) { -> input, index { input[:users][index][:tasks] } }
91
+
92
+ let(:input) do
93
+ { users: [
94
+ {
95
+ name: 'Jane',
96
+ tasks: [{ title: 'Jane Task One' }, { title: 'Jane Task Two' }]
97
+ },
98
+ {
99
+ name: 'Joe',
100
+ tasks: [{ title: 'Joe Task One' }]
101
+ }
102
+ ]}
103
+ end
104
+
105
+ it 'evaluates the input and calls command' do
106
+ command.call(input, input[:users])
107
+
108
+ expect(container.relation(:tasks)).to match_array([
109
+ { user: 'Jane', title: 'Jane Task One' },
110
+ { user: 'Jane', title: 'Jane Task Two' },
111
+ { user: 'Joe', title: 'Joe Task One' }
112
+ ])
113
+ end
114
+ end
115
+
116
+ context 'with an update command' do
117
+ subject(:command) do
118
+ ROM::Commands::Lazy[update_user].new(
119
+ update_user, evaluator, -> cmd, user { cmd.by_name(user[:name]) })
120
+ end
121
+
122
+ before do
123
+ create_user[jane]
124
+ end
125
+
126
+ it 'evaluates the input, restricts the relation and calls its command' do
127
+ input = { user: { name: 'Jane', email: 'jane.doe@rom-rb.org' } }
128
+ command.call(input)
129
+
130
+ expect(container.relation(:users)).to match_array([input[:user]])
131
+ end
132
+ end
133
+
134
+ context 'with an update command for a child tuple' do
135
+ subject(:command) do
136
+ ROM::Commands::Lazy[update_task].new(
137
+ update_task,
138
+ evaluator,
139
+ -> cmd, user, task { cmd.by_user(user[:name]).by_title(task[:title]) }
140
+ )
141
+ end
38
142
 
39
- it 'evaluates the input and calls command' do
40
- command.call(user)
143
+ let(:evaluator) { -> input { input[:user][:task] } }
41
144
 
42
- expect(rom.relation(:users)).to match_array([
43
- { name: 'Jane' }
44
- ])
145
+ let(:jane) { { name: 'Jane' } }
146
+ let(:jane_task) { { user: 'Jane', title: 'Jane Task', priority: 1 } }
147
+
148
+ let(:input) { { user: jane.merge(task: jane_task) } }
149
+
150
+ before do
151
+ create_user[jane]
152
+ create_task[user: 'Jane', title: 'Jane Task', priority: 2]
153
+ end
154
+
155
+ it 'evaluates the input, restricts the relation and calls its command' do
156
+ command.call(input, input[:user])
157
+
158
+ expect(container.relation(:users)).to match_array([jane])
159
+
160
+ expect(container.relation(:tasks)).to match_array([jane_task])
161
+ end
162
+ end
163
+
164
+ context 'with an update command for child tuples' do
165
+ subject(:command) do
166
+ ROM::Commands::Lazy[update_task].new(
167
+ update_task,
168
+ evaluator,
169
+ -> cmd, user, task { cmd.by_user(user[:name]).by_title(task[:title]) }
170
+ )
171
+ end
172
+
173
+ let(:evaluator) { -> input { input[:user][:tasks] } }
174
+
175
+ let(:jane) { { name: 'Jane' } }
176
+ let(:jane_tasks) {
177
+ [
178
+ { user: 'Jane', title: 'Jane Task One', priority: 2 },
179
+ { user: 'Jane', title: 'Jane Task Two', priority: 3 }
180
+ ]
181
+ }
182
+
183
+ let(:input) { { user: jane.merge(tasks: jane_tasks) } }
184
+
185
+ before do
186
+ create_user[jane]
187
+ create_task[user: 'Jane', title: 'Jane Task One', priority: 3]
188
+ create_task[user: 'Jane', title: 'Jane Task Two', priority: 4]
189
+ end
190
+
191
+ it 'evaluates the input, restricts the relation and calls its command' do
192
+ command.call(input, input[:user])
193
+
194
+ expect(container.relation(:users)).to match_array([jane])
195
+
196
+ expect(container.relation(:tasks)).to match_array(jane_tasks)
197
+ end
198
+ end
199
+
200
+ context 'with an update command for many parents and their children' do
201
+ subject(:command) do
202
+ ROM::Commands::Lazy[update_task].new(
203
+ update_task,
204
+ evaluator,
205
+ -> cmd, user, task { cmd.by_user(user[:name]).by_title(task[:title]) }
206
+ )
207
+ end
208
+
209
+ let(:evaluator) { -> input, index { input[:users][index][:tasks] } }
210
+
211
+ let(:input) do
212
+ { users: [
213
+ {
214
+ name: 'Jane',
215
+ tasks: [
216
+ { title: 'Jane Task One', priority: 1 },
217
+ { title: 'Jane Task Two', priority: 2 }
218
+ ]
219
+ },
220
+ {
221
+ name: 'Joe',
222
+ tasks: [{ title: 'Joe Task One', priority: 1 }]
223
+ }
224
+ ]}
225
+ end
226
+
227
+ before do
228
+ create_user[name: 'Jane']
229
+ create_user[name: 'Joe']
230
+
231
+ create_task[user: 'Jane', title: 'Jane Task One']
232
+ create_task[user: 'Jane', title: 'Jane Task Two']
233
+ create_task[user: 'Joe', title: 'Joe Task One']
234
+ end
235
+
236
+ it 'evaluates the input and calls its command' do
237
+ command.call(input, input[:users])
238
+
239
+ expect(container.relation(:tasks)).to match_array([
240
+ { user: 'Jane', title: 'Jane Task One', priority: 1 },
241
+ { user: 'Jane', title: 'Jane Task Two', priority: 2 },
242
+ { user: 'Joe', title: 'Joe Task One', priority: 1 }
243
+ ])
244
+ end
245
+ end
246
+
247
+ context 'with a delete command' do
248
+ subject(:command) do
249
+ ROM::Commands::Lazy[delete_user].new(
250
+ delete_user,
251
+ evaluator,
252
+ -> cmd, user { cmd.by_name(user[:name]) }
253
+ )
254
+ end
255
+
256
+ let(:joe) { { name: 'Joe' } }
257
+
258
+ before do
259
+ create_user[jane]
260
+ create_user[joe]
261
+ end
262
+
263
+ it 'restricts the relation and calls its command' do
264
+ command.call(input)
265
+
266
+ expect(container.relation(:users)).to match_array([joe])
267
+ end
45
268
  end
46
269
  end
47
270
 
48
271
  describe '#>>' do
49
- subject(:command) { ROM::Commands::Lazy.new(create_user, evaluator) }
272
+ subject(:command) { ROM::Commands::Lazy[create_user].new(create_user, evaluator) }
50
273
 
51
274
  it 'composes with another command' do
52
275
  expect(command >> create_task).to be_instance_of(ROM::Commands::Composite)
@@ -54,7 +277,7 @@ describe ROM::Commands::Lazy do
54
277
  end
55
278
 
56
279
  describe '#combine' do
57
- subject(:command) { ROM::Commands::Lazy.new(create_user, evaluator) }
280
+ subject(:command) { ROM::Commands::Lazy[create_user].new(create_user, evaluator) }
58
281
 
59
282
  it 'combines with another command' do
60
283
  expect(command.combine(create_task)).to be_instance_of(ROM::Commands::Graph)
@@ -62,23 +285,11 @@ describe ROM::Commands::Lazy do
62
285
  end
63
286
 
64
287
  describe '#method_missing' do
65
- subject(:command) { ROM::Commands::Lazy.new(update_user, evaluator) }
66
-
67
- it 'forwards to command' do
68
- rom.relations[:users] << { name: 'Jane' } << { name: 'Joe' }
69
-
70
- new_command = command.by_name('Jane')
71
- new_command.call(user: { name: 'Jane Doe' })
72
-
73
- expect(rom.relation(:users)).to match_array([
74
- { name: 'Jane Doe' },
75
- { name: 'Joe' }
76
- ])
77
- end
288
+ subject(:command) { ROM::Commands::Lazy[update_user].new(update_user, evaluator) }
78
289
 
79
- it 'return original response if it was not a command' do
290
+ it 'returns original response if it was not a command' do
80
291
  response = command.result
81
- expect(response).to be(:many)
292
+ expect(response).to be(:one)
82
293
  end
83
294
 
84
295
  it 'raises error when message is unknown' do