iknow_view_models 3.1.5 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +6 -6
  3. data/.rubocop.yml +18 -0
  4. data/Appraisals +6 -6
  5. data/Gemfile +6 -2
  6. data/Rakefile +5 -5
  7. data/gemfiles/rails_5_2.gemfile +5 -5
  8. data/gemfiles/rails_6_0.gemfile +9 -0
  9. data/iknow_view_models.gemspec +40 -38
  10. data/lib/iknow_view_models.rb +9 -7
  11. data/lib/iknow_view_models/version.rb +1 -1
  12. data/lib/view_model.rb +31 -17
  13. data/lib/view_model/access_control.rb +5 -2
  14. data/lib/view_model/access_control/composed.rb +10 -9
  15. data/lib/view_model/access_control/open.rb +2 -0
  16. data/lib/view_model/access_control/read_only.rb +2 -0
  17. data/lib/view_model/access_control/tree.rb +11 -6
  18. data/lib/view_model/access_control_error.rb +4 -1
  19. data/lib/view_model/active_record.rb +13 -12
  20. data/lib/view_model/active_record/association_data.rb +3 -2
  21. data/lib/view_model/active_record/association_manipulation.rb +6 -4
  22. data/lib/view_model/active_record/cache.rb +114 -34
  23. data/lib/view_model/active_record/cache/cacheable_view.rb +2 -2
  24. data/lib/view_model/active_record/collection_nested_controller.rb +3 -3
  25. data/lib/view_model/active_record/controller.rb +53 -1
  26. data/lib/view_model/active_record/controller_base.rb +4 -1
  27. data/lib/view_model/active_record/nested_controller_base.rb +1 -0
  28. data/lib/view_model/active_record/update_context.rb +8 -6
  29. data/lib/view_model/active_record/update_data.rb +32 -30
  30. data/lib/view_model/active_record/update_operation.rb +17 -13
  31. data/lib/view_model/active_record/visitor.rb +0 -1
  32. data/lib/view_model/after_transaction_runner.rb +2 -2
  33. data/lib/view_model/callbacks.rb +3 -1
  34. data/lib/view_model/controller.rb +13 -3
  35. data/lib/view_model/deserialization_error.rb +15 -12
  36. data/lib/view_model/error.rb +12 -10
  37. data/lib/view_model/error_view.rb +3 -1
  38. data/lib/view_model/migratable_view.rb +78 -0
  39. data/lib/view_model/migration.rb +48 -0
  40. data/lib/view_model/migration/no_path_error.rb +26 -0
  41. data/lib/view_model/migration/one_way_error.rb +24 -0
  42. data/lib/view_model/migration/unspecified_version_error.rb +24 -0
  43. data/lib/view_model/migrator.rb +108 -0
  44. data/lib/view_model/record.rb +15 -14
  45. data/lib/view_model/reference.rb +3 -1
  46. data/lib/view_model/references.rb +8 -5
  47. data/lib/view_model/registry.rb +1 -1
  48. data/lib/view_model/schemas.rb +9 -4
  49. data/lib/view_model/serialization_error.rb +4 -1
  50. data/lib/view_model/serialize_context.rb +4 -4
  51. data/lib/view_model/test_helpers.rb +8 -3
  52. data/lib/view_model/test_helpers/arvm_builder.rb +21 -15
  53. data/lib/view_model/traversal_context.rb +8 -5
  54. data/nix/dependencies.nix +5 -0
  55. data/nix/gem/generate.rb +2 -1
  56. data/shell.nix +8 -3
  57. data/test/.rubocop.yml +14 -0
  58. data/test/helpers/arvm_test_models.rb +12 -9
  59. data/test/helpers/arvm_test_utilities.rb +5 -3
  60. data/test/helpers/controller_test_helpers.rb +44 -28
  61. data/test/helpers/match_enumerator.rb +1 -0
  62. data/test/helpers/query_logging.rb +2 -1
  63. data/test/helpers/test_access_control.rb +5 -3
  64. data/test/helpers/viewmodel_spec_helpers.rb +88 -22
  65. data/test/unit/view_model/access_control_test.rb +144 -144
  66. data/test/unit/view_model/active_record/alias_test.rb +15 -13
  67. data/test/unit/view_model/active_record/belongs_to_test.rb +40 -39
  68. data/test/unit/view_model/active_record/cache_test.rb +68 -31
  69. data/test/unit/view_model/active_record/cloner_test.rb +67 -63
  70. data/test/unit/view_model/active_record/controller_test.rb +71 -38
  71. data/test/unit/view_model/active_record/counter_test.rb +10 -9
  72. data/test/unit/view_model/active_record/customization_test.rb +59 -58
  73. data/test/unit/view_model/active_record/has_many_test.rb +112 -111
  74. data/test/unit/view_model/active_record/has_many_through_poly_test.rb +15 -14
  75. data/test/unit/view_model/active_record/has_many_through_test.rb +33 -38
  76. data/test/unit/view_model/active_record/has_one_test.rb +37 -36
  77. data/test/unit/view_model/active_record/migration_test.rb +161 -0
  78. data/test/unit/view_model/active_record/namespacing_test.rb +19 -17
  79. data/test/unit/view_model/active_record/poly_test.rb +44 -45
  80. data/test/unit/view_model/active_record/shared_test.rb +30 -28
  81. data/test/unit/view_model/active_record/version_test.rb +9 -7
  82. data/test/unit/view_model/active_record_test.rb +72 -72
  83. data/test/unit/view_model/callbacks_test.rb +19 -15
  84. data/test/unit/view_model/controller_test.rb +4 -2
  85. data/test/unit/view_model/record_test.rb +92 -97
  86. data/test/unit/view_model/traversal_context_test.rb +4 -5
  87. data/test/unit/view_model_test.rb +18 -16
  88. metadata +36 -12
  89. data/.travis.yml +0 -31
  90. data/appveyor.yml +0 -22
  91. data/gemfiles/rails_6_0_beta.gemfile +0 -9
@@ -1,14 +1,16 @@
1
- require "minitest/autorun"
2
- require "minitest/unit"
3
- require "minitest/hooks"
1
+ # frozen_string_literal: true
4
2
 
5
- require_relative "../../../helpers/arvm_test_models.rb"
6
- require_relative "../../../helpers/viewmodel_spec_helpers.rb"
3
+ require 'minitest/autorun'
4
+ require 'minitest/unit'
5
+ require 'minitest/hooks'
6
+
7
+ require_relative '../../../helpers/arvm_test_models'
8
+ require_relative '../../../helpers/viewmodel_spec_helpers'
7
9
 
8
10
  # MiniTest::Spec.register_spec_type(/./, Minitest::HooksSpec)
9
11
 
10
- require "view_model"
11
- require "view_model/active_record"
12
+ require 'view_model'
13
+ require 'view_model/active_record'
12
14
 
13
15
  class ViewModel::ActiveRecord
14
16
  class ClonerTest < ActiveSupport::TestCase
@@ -18,7 +20,7 @@ class ViewModel::ActiveRecord
18
20
  let(:viewmodel) { create_viewmodel! }
19
21
  let(:model) { viewmodel.model }
20
22
 
21
- describe "with single model" do
23
+ describe 'with single model' do
22
24
  include ViewModelSpecHelpers::Single
23
25
 
24
26
  def model_attributes
@@ -26,15 +28,15 @@ class ViewModel::ActiveRecord
26
28
  end
27
29
 
28
30
  def new_model
29
- model_class.new(name: "a", nonview: "b")
31
+ model_class.new(name: 'a', nonview: 'b')
30
32
  end
31
33
 
32
- it "persists the test setup" do
34
+ it 'persists the test setup' do
33
35
  assert(viewmodel.model.persisted?)
34
36
  refute(viewmodel.model.new_record?)
35
37
  end
36
38
 
37
- it "can clone the model" do
39
+ it 'can clone the model' do
38
40
  clone_model = Cloner.new.clone(viewmodel)
39
41
  assert(clone_model.new_record?)
40
42
  assert_nil(clone_model.id)
@@ -45,75 +47,75 @@ class ViewModel::ActiveRecord
45
47
  end
46
48
 
47
49
  class IgnoreParentCloner < Cloner
48
- def visit_model_view(node, model)
50
+ def visit_model_view(_node, _model)
49
51
  ignore!
50
52
  end
51
53
  end
52
54
 
53
- it "can ignore a model" do
55
+ it 'can ignore a model' do
54
56
  clone_model = IgnoreParentCloner.new.clone(viewmodel)
55
57
  assert_nil(clone_model)
56
58
  end
57
59
 
58
60
  class IgnoreAllCloner < Cloner
59
- def pre_visit(node, model)
61
+ def pre_visit(_node, _model)
60
62
  ignore!
61
63
  end
62
64
  end
63
65
 
64
- it "can ignore a model in pre-visit" do
66
+ it 'can ignore a model in pre-visit' do
65
67
  clone_model = IgnoreAllCloner.new.clone(viewmodel)
66
68
  assert_nil(clone_model)
67
69
  end
68
70
 
69
71
  class AlterAttributeCloner < Cloner
70
- def visit_model_view(node, model)
71
- model.name = "changed"
72
+ def visit_model_view(_node, model)
73
+ model.name = 'changed'
72
74
  end
73
75
  end
74
76
 
75
- it "can alter a model attribute" do
77
+ it 'can alter a model attribute' do
76
78
  clone_model = AlterAttributeCloner.new.clone(viewmodel)
77
79
  assert(clone_model.new_record?)
78
80
  assert_nil(clone_model.id)
79
- assert_equal("changed", clone_model.name)
80
- refute_equal("changed", model.name)
81
+ assert_equal('changed', clone_model.name)
82
+ refute_equal('changed', model.name)
81
83
  assert_equal(model.nonview, clone_model.nonview)
82
84
  clone_model.save!
83
85
  refute_equal(model, clone_model)
84
86
  end
85
87
 
86
88
  class PostAlterAttributeCloner < Cloner
87
- def end_visit_model_view(node, model)
88
- model.name = "changed"
89
+ def end_visit_model_view(_node, model)
90
+ model.name = 'changed'
89
91
  end
90
92
  end
91
93
 
92
- it "can alter a model attribute post-visit" do
94
+ it 'can alter a model attribute post-visit' do
93
95
  clone_model = PostAlterAttributeCloner.new.clone(viewmodel)
94
96
  assert(clone_model.new_record?)
95
97
  assert_nil(clone_model.id)
96
- assert_equal("changed", clone_model.name)
97
- refute_equal("changed", model.name)
98
+ assert_equal('changed', clone_model.name)
99
+ refute_equal('changed', model.name)
98
100
  assert_equal(model.nonview, clone_model.nonview)
99
101
  clone_model.save!
100
102
  refute_equal(model, clone_model)
101
103
  end
102
104
  end
103
105
 
104
- describe "with a child" do
106
+ describe 'with a child' do
105
107
  def new_child_model
106
- child_model_class.new(name: "b")
108
+ child_model_class.new(name: 'b')
107
109
  end
108
110
 
109
111
  def new_model
110
- model_class.new(name: "a", child: new_child_model)
112
+ model_class.new(name: 'a', child: new_child_model)
111
113
  end
112
114
 
113
115
  module BehavesLikeConstructingAChild
114
116
  extend ActiveSupport::Concern
115
117
  included do
116
- it "persists the test setup" do
118
+ it 'persists the test setup' do
117
119
  assert(viewmodel.model.persisted?)
118
120
  refute(viewmodel.model.new_record?)
119
121
  assert(viewmodel.model.child.persisted?)
@@ -123,7 +125,7 @@ class ViewModel::ActiveRecord
123
125
  end
124
126
 
125
127
  class IgnoreChildAssociationCloner < Cloner
126
- def visit_model_view(node, model)
128
+ def visit_model_view(_node, _model)
127
129
  ignore_association!(:child)
128
130
  end
129
131
  end
@@ -131,7 +133,7 @@ class ViewModel::ActiveRecord
131
133
  module BehavesLikeCloningAChild
132
134
  extend ActiveSupport::Concern
133
135
  included do
134
- it "can clone the model and child" do
136
+ it 'can clone the model and child' do
135
137
  clone_model = Cloner.new.clone(viewmodel)
136
138
 
137
139
  assert(clone_model.new_record?)
@@ -148,7 +150,7 @@ class ViewModel::ActiveRecord
148
150
  refute_equal(model.child, clone_model.child)
149
151
  end
150
152
 
151
- it "can ignore the child association" do
153
+ it 'can ignore the child association' do
152
154
  clone_model = IgnoreChildAssociationCloner.new.clone(viewmodel)
153
155
 
154
156
  assert(clone_model.new_record?)
@@ -160,66 +162,67 @@ class ViewModel::ActiveRecord
160
162
  end
161
163
  end
162
164
 
163
- describe "as belongs_to" do
165
+ describe 'as belongs_to' do
164
166
  include ViewModelSpecHelpers::ParentAndBelongsToChild
165
167
  include BehavesLikeConstructingAChild
166
168
  include BehavesLikeCloningAChild
167
169
  end
168
170
 
169
- describe "as has_one" do
171
+ describe 'as has_one' do
170
172
  include ViewModelSpecHelpers::ParentAndHasOneChild
171
173
  include BehavesLikeConstructingAChild
172
174
  include BehavesLikeCloningAChild
173
175
  end
174
176
 
175
- describe "as belongs_to shared child" do
177
+ describe 'as belongs_to shared child' do
176
178
  include ViewModelSpecHelpers::ParentAndSharedBelongsToChild
177
179
  include BehavesLikeConstructingAChild
178
- it "can clone the model but not the child" do
179
- clone_model = Cloner.new.clone(viewmodel)
180
180
 
181
- assert(clone_model.new_record?)
182
- assert_nil(clone_model.id)
183
- assert_equal(model.name, clone_model.name)
181
+ it 'can clone the model but not the child' do
182
+ clone_model = Cloner.new.clone(viewmodel)
184
183
 
185
- clone_child = clone_model.child
186
- refute(clone_child.new_record?)
187
- assert_equal(model.child, clone_child)
184
+ assert(clone_model.new_record?)
185
+ assert_nil(clone_model.id)
186
+ assert_equal(model.name, clone_model.name)
188
187
 
189
- clone_model.save!
190
- refute_equal(model, clone_model)
191
- assert_equal(model.child, clone_model.child)
192
- end
188
+ clone_child = clone_model.child
189
+ refute(clone_child.new_record?)
190
+ assert_equal(model.child, clone_child)
191
+
192
+ clone_model.save!
193
+ refute_equal(model, clone_model)
194
+ assert_equal(model.child, clone_model.child)
195
+ end
193
196
  end
194
197
  end
195
198
 
196
199
  class IgnoreChildrenAssociationCloner < Cloner
197
- def visit_model_view(node, model)
200
+ def visit_model_view(_node, _model)
198
201
  ignore_association!(:children)
199
202
  end
200
203
  end
201
204
 
202
- describe "with has_many children" do
205
+ describe 'with has_many children' do
203
206
  include ViewModelSpecHelpers::ParentAndHasManyChildren
204
207
  def new_child_models
205
- ["b", "c"].map { |n| child_model_class.new(name: n) }
208
+ ['b', 'c'].map { |n| child_model_class.new(name: n) }
206
209
  end
207
210
 
208
211
  def new_model
209
- model_class.new(name: "a", children: new_child_models)
212
+ model_class.new(name: 'a', children: new_child_models)
210
213
  end
211
214
 
212
- it "persists the test setup" do
215
+ it 'persists the test setup' do
213
216
  assert(viewmodel.model.persisted?)
214
217
  refute(viewmodel.model.new_record?)
215
218
  assert_equal(2, viewmodel.model.children.size)
216
- viewmodel.model.children.each do | child|
219
+ viewmodel.model.children.each do |child|
217
220
  assert(child.persisted?)
218
221
  refute(child.new_record?)
219
222
  end
220
223
  end
221
224
 
222
- it "can clone the model" do
225
+ it 'can clone the model' do
223
226
  clone_model = Cloner.new.clone(viewmodel)
224
227
 
225
228
  assert(clone_model.new_record?)
@@ -244,9 +247,10 @@ class ViewModel::ActiveRecord
244
247
  class IgnoreFirstChildCloner < Cloner
245
248
  def initialize
246
249
  @ignored_first = false
250
+ super
247
251
  end
248
252
 
249
- def visit_child_view(node, model)
253
+ def visit_child_view(_node, _model)
250
254
  unless @ignored_first
251
255
  @ignored_first = true
252
256
  ignore!
@@ -254,7 +258,7 @@ class ViewModel::ActiveRecord
254
258
  end
255
259
  end
256
260
 
257
- it "can ignore subset of children" do
261
+ it 'can ignore subset of children' do
258
262
  clone_model = IgnoreFirstChildCloner.new.clone(viewmodel)
259
263
 
260
264
  assert(clone_model.new_record?)
@@ -265,7 +269,7 @@ class ViewModel::ActiveRecord
265
269
  assert_equal(model.children[1].name, clone_model.children[0].name)
266
270
  end
267
271
 
268
- it "can ignore the children association" do
272
+ it 'can ignore the children association' do
269
273
  clone_model = IgnoreChildrenAssociationCloner.new.clone(viewmodel)
270
274
 
271
275
  assert(clone_model.new_record?)
@@ -276,19 +280,19 @@ class ViewModel::ActiveRecord
276
280
  end
277
281
  end
278
282
 
279
- describe "with has_many_through shared children" do
283
+ describe 'with has_many_through shared children' do
280
284
  include ViewModelSpecHelpers::ParentAndHasManyThroughChildren
281
285
  def new_model_children
282
- ["b", "c"].map.with_index do |n, i|
286
+ ['b', 'c'].map.with_index do |n, i|
283
287
  join_model_class.new(child: child_model_class.new(name: n), position: i)
284
288
  end
285
289
  end
286
290
 
287
291
  def new_model
288
- model_class.new( name: "a", model_children: new_model_children)
292
+ model_class.new(name: 'a', model_children: new_model_children)
289
293
  end
290
294
 
291
- it "persists the test setup" do
295
+ it 'persists the test setup' do
292
296
  assert(viewmodel.model.persisted?)
293
297
  refute(viewmodel.model.new_record?)
294
298
  assert_equal(2, viewmodel.model.model_children.size)
@@ -301,7 +305,7 @@ class ViewModel::ActiveRecord
301
305
  end
302
306
  end
303
307
 
304
- it "can clone the model and join model but not the child" do
308
+ it 'can clone the model and join model but not the child' do
305
309
  clone_model = Cloner.new.clone(viewmodel)
306
310
 
307
311
  assert(clone_model.new_record?)
@@ -325,7 +329,7 @@ class ViewModel::ActiveRecord
325
329
  end
326
330
  end
327
331
 
328
- it "can ignore the children association" do
332
+ it 'can ignore the children association' do
329
333
  clone_model = IgnoreChildrenAssociationCloner.new.clone(viewmodel)
330
334
 
331
335
  assert(clone_model.new_record?)
@@ -1,14 +1,14 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
- require "minitest/autorun"
3
+ require 'minitest/autorun'
4
4
  require 'minitest/unit'
5
5
  require 'minitest/hooks'
6
6
 
7
- require "view_model"
8
- require "view_model/active_record"
7
+ require 'view_model'
8
+ require 'view_model/active_record'
9
9
 
10
- require_relative "../../../helpers/controller_test_helpers.rb"
11
- require_relative "../../../helpers/callback_tracer.rb"
10
+ require_relative '../../../helpers/controller_test_helpers'
11
+ require_relative '../../../helpers/callback_tracer'
12
12
 
13
13
  class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
14
14
  include ARVMTestUtilities
@@ -88,7 +88,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
88
88
  super
89
89
  @parent = Parent.create(name: 'p',
90
90
  children: [Child.new(name: 'c1', position: 1.0),
91
- Child.new(name: 'c2', position: 2.0)],
91
+ Child.new(name: 'c2', position: 2.0),],
92
92
  label: Label.new,
93
93
  target: Target.new)
94
94
 
@@ -109,8 +109,26 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
109
109
  assert_all_hooks_nested_inside_parent_hook(parentcontroller.hook_trace)
110
110
  end
111
111
 
112
+ def test_migrated_show
113
+ parentcontroller = ParentController.new(id: @parent.id, versions: { ParentView.view_name => 1 })
114
+ parentcontroller.invoke(:show)
115
+
116
+ expected_view = @parent_view.to_hash
117
+ .except('name')
118
+ .merge('old_name' => @parent.name,
119
+ ViewModel::VERSION_ATTRIBUTE => 1,
120
+ ViewModel::MIGRATED_ATTRIBUTE => true)
121
+
122
+ assert_equal({ 'data' => expected_view },
123
+ parentcontroller.hash_response)
124
+
125
+ assert_equal(200, parentcontroller.status)
126
+
127
+ assert_all_hooks_nested_inside_parent_hook(parentcontroller.hook_trace)
128
+ end
129
+
112
130
  def test_index
113
- p2 = Parent.create(name: "p2")
131
+ p2 = Parent.create(name: 'p2')
114
132
  p2_view = ParentView.new(p2)
115
133
 
116
134
  parentcontroller = ParentController.new
@@ -119,7 +137,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
119
137
  assert_equal(200, parentcontroller.status)
120
138
 
121
139
  assert_equal(parentcontroller.hash_response,
122
- { "data" => [@parent_view.to_hash, p2_view.to_hash] })
140
+ { 'data' => [@parent_view.to_hash, p2_view.to_hash] })
123
141
 
124
142
  assert_all_hooks_nested_inside_parent_hook(parentcontroller.hook_trace)
125
143
  end
@@ -131,7 +149,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
131
149
  'label' => { '_type' => 'Label', 'text' => 'l' },
132
150
  'target' => { '_type' => 'Target', 'text' => 't' },
133
151
  'children' => [{ '_type' => 'Child', 'name' => 'c1' },
134
- { '_type' => 'Child', 'name' => 'c2' }]
152
+ { '_type' => 'Child', 'name' => 'c2' },],
135
153
  }
136
154
 
137
155
  parentcontroller = ParentController.new(data: data)
@@ -148,6 +166,22 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
148
166
  assert_all_hooks_nested_inside_parent_hook(parentcontroller.hook_trace)
149
167
  end
150
168
 
169
+ def test_migrated_create
170
+ data = {
171
+ '_type' => 'Parent',
172
+ '_version' => 1,
173
+ 'old_name' => 'p2',
174
+ }
175
+
176
+ parentcontroller = ParentController.new(data: data, versions: { ParentView.view_name => 1 })
177
+ parentcontroller.invoke(:create)
178
+
179
+ assert_equal(200, parentcontroller.status)
180
+
181
+ p2 = Parent.where(name: 'p2').first
182
+ assert(p2.present?, 'p2 created')
183
+ end
184
+
151
185
  def test_create_empty
152
186
  parentcontroller = ParentController.new(data: [])
153
187
  parentcontroller.invoke(:create)
@@ -206,10 +240,10 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
206
240
  'status' => 404,
207
241
  'detail' => "Couldn't find Parent(s) with id(s)=[9999]",
208
242
  'title' => nil,
209
- 'code' => "DeserializationError.NotFound",
210
- 'meta' => { 'nodes' => [{ '_type' => "Parent", 'id' => 9999 }]},
243
+ 'code' => 'DeserializationError.NotFound',
244
+ 'meta' => { 'nodes' => [{ '_type' => 'Parent', 'id' => 9999 }] },
211
245
  'exception' => nil,
212
- 'causes' => nil }},
246
+ 'causes' => nil } },
213
247
  parentcontroller.hash_response)
214
248
  end
215
249
 
@@ -227,13 +261,13 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
227
261
  'status' => 400,
228
262
  'detail' => 'Validation failed: \'age\' must be less than 42',
229
263
  'title' => nil,
230
- 'code' => "DeserializationError.Validation",
231
- 'meta' => { 'nodes' => [{ '_type' => "Child", 'id' => nil }],
264
+ 'code' => 'DeserializationError.Validation',
265
+ 'meta' => { 'nodes' => [{ '_type' => 'Child', 'id' => nil }],
232
266
  'attribute' => 'age',
233
267
  'message' => 'must be less than 42',
234
- 'details' => { 'error' => 'less_than', 'value' => 42, 'count' => 42 }},
268
+ 'details' => { 'error' => 'less_than', 'value' => 42, 'count' => 42 } },
235
269
  'exception' => nil,
236
- 'causes' => nil }},
270
+ 'causes' => nil } },
237
271
  parentcontroller.hash_response)
238
272
  end
239
273
 
@@ -245,9 +279,9 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
245
279
  parentcontroller.invoke(:create)
246
280
 
247
281
  assert_equal(400, parentcontroller.status)
248
- assert_match(%r{check constraint}i,
249
- parentcontroller.hash_response["error"]["detail"],
250
- "Database error propagated")
282
+ assert_match(/check constraint/i,
283
+ parentcontroller.hash_response['error']['detail'],
284
+ 'Database error propagated')
251
285
  end
252
286
 
253
287
  def test_destroy_missing
@@ -260,8 +294,8 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
260
294
  'status' => 404,
261
295
  'detail' => "Couldn't find Parent(s) with id(s)=[9999]",
262
296
  'title' => nil,
263
- 'code' => "DeserializationError.NotFound",
264
- 'meta' => { "nodes" => [{"_type" => "Parent", "id" => 9999 }] },
297
+ 'code' => 'DeserializationError.NotFound',
298
+ 'meta' => { 'nodes' => [{ '_type' => 'Parent', 'id' => 9999 }] },
265
299
  'exception' => nil,
266
300
  'causes' => nil } },
267
301
  parentcontroller.hash_response)
@@ -308,7 +342,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
308
342
 
309
343
  @parent.reload
310
344
 
311
- assert_equal(%w{c1 c2 c3}, @parent.children.order(:position).pluck(:name))
345
+ assert_equal(%w[c1 c2 c3], @parent.children.order(:position).pluck(:name))
312
346
  assert_equal({ 'data' => ChildView.new(@parent.children.last).to_hash },
313
347
  childcontroller.hash_response)
314
348
 
@@ -317,7 +351,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
317
351
 
318
352
  def test_nested_collection_append_many
319
353
  data = [{ '_type' => 'Child', 'name' => 'c3' },
320
- { '_type' => 'Child', 'name' => 'c4' }]
354
+ { '_type' => 'Child', 'name' => 'c4' },]
321
355
 
322
356
  childcontroller = ChildController.new(parent_id: @parent.id, data: data)
323
357
  childcontroller.invoke(:append)
@@ -326,8 +360,8 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
326
360
 
327
361
  @parent.reload
328
362
 
329
- assert_equal(%w{c1 c2 c3 c4}, @parent.children.order(:position).pluck(:name))
330
- new_children_hashes = @parent.children.last(2).map{ |c| ChildView.new(c).to_hash }
363
+ assert_equal(%w[c1 c2 c3 c4], @parent.children.order(:position).pluck(:name))
364
+ new_children_hashes = @parent.children.last(2).map { |c| ChildView.new(c).to_hash }
331
365
  assert_equal({ 'data' => new_children_hashes },
332
366
  childcontroller.hash_response)
333
367
 
@@ -339,8 +373,8 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
339
373
  # Parent.children
340
374
  old_children = @parent.children
341
375
 
342
- data = [{'_type' => 'Child', 'name' => 'newc1'},
343
- {'_type' => 'Child', 'name' => 'newc2'}]
376
+ data = [{ '_type' => 'Child', 'name' => 'newc1' },
377
+ { '_type' => 'Child', 'name' => 'newc2' },]
344
378
 
345
379
  childcontroller = ChildController.new(parent_id: @parent.id, data: data)
346
380
  childcontroller.invoke(:replace)
@@ -349,14 +383,14 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
349
383
 
350
384
  @parent.reload
351
385
 
352
- assert_equal(%w{newc1 newc2}, @parent.children.order(:position).pluck(:name))
386
+ assert_equal(%w[newc1 newc2], @parent.children.order(:position).pluck(:name))
353
387
  assert_predicate(Child.where(id: old_children.map(&:id)), :empty?)
354
388
 
355
389
  assert_all_hooks_nested_inside_parent_hook(childcontroller.hook_trace)
356
390
  end
357
391
 
358
392
  def test_nested_collection_replace_bad_data
359
- data = [{ "name" => "nc" }]
393
+ data = [{ 'name' => 'nc' }]
360
394
  childcontroller = ChildController.new(parent_id: @parent.id, data: data)
361
395
 
362
396
  childcontroller.invoke(:replace)
@@ -375,7 +409,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
375
409
 
376
410
  @parent.reload
377
411
 
378
- assert_equal(%w{c2}, @parent.children.order(:position).pluck(:name))
412
+ assert_equal(%w[c2], @parent.children.order(:position).pluck(:name))
379
413
  assert_predicate(Child.where(id: old_child.id), :empty?)
380
414
 
381
415
  assert_all_hooks_nested_inside_parent_hook(childcontroller.hook_trace)
@@ -407,7 +441,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
407
441
 
408
442
  @parent.reload
409
443
 
410
- assert_equal(%w{c2}, @parent.children.order(:position).pluck(:name))
444
+ assert_equal(%w[c2], @parent.children.order(:position).pluck(:name))
411
445
  assert_predicate(Child.where(id: old_child.id), :empty?)
412
446
  end
413
447
 
@@ -430,7 +464,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
430
464
  childcontroller.hash_response)
431
465
  end
432
466
 
433
- def test_nested_collection_show
467
+ def test_nested_collection_show
434
468
  old_child = @parent.children.first
435
469
 
436
470
  childcontroller = ChildController.new(id: old_child.id)
@@ -440,15 +474,14 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
440
474
  childcontroller.hash_response)
441
475
 
442
476
  assert_equal(200, childcontroller.status)
443
- end
444
-
477
+ end
445
478
 
446
479
  ## Single association
447
480
 
448
481
  def test_nested_singular_replace_from_parent
449
482
  old_label = @parent.label
450
483
 
451
- data = {'_type' => 'Label', 'text' => 'new label'}
484
+ data = { '_type' => 'Label', 'text' => 'new label' }
452
485
  labelcontroller = LabelController.new(parent_id: @parent.id, data: data)
453
486
  labelcontroller.invoke(:create_associated)
454
487
 
@@ -502,7 +535,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
502
535
  def test_nested_singular_update_from_parent
503
536
  old_label = @parent.label
504
537
 
505
- data = {'_type' => 'Label', 'id' => old_label.id, 'text' => 'new label'}
538
+ data = { '_type' => 'Label', 'id' => old_label.id, 'text' => 'new label' }
506
539
  labelcontroller = LabelController.new(parent_id: @parent.id, data: data)
507
540
  labelcontroller.invoke(:create_associated)
508
541
 
@@ -549,7 +582,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
549
582
  def test_nested_singular_update
550
583
  old_label = @parent.label
551
584
 
552
- data = {'_type' => 'Label', 'id' => old_label.id, 'text' => 'new label'}
585
+ data = { '_type' => 'Label', 'id' => old_label.id, 'text' => 'new label' }
553
586
  labelcontroller = LabelController.new(data: data)
554
587
  labelcontroller.invoke(:create)
555
588