iknow_view_models 3.1.8 → 3.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) 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 +17 -15
  20. data/lib/view_model/active_record/association_data.rb +2 -1
  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 +68 -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 +0 -1
  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 +14 -2
  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 +2 -1
  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 +55 -32
  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 +113 -65
  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 +158 -145
  86. data/test/unit/view_model/registry_test.rb +38 -0
  87. data/test/unit/view_model/traversal_context_test.rb +4 -5
  88. data/test/unit/view_model_test.rb +18 -16
  89. metadata +38 -12
  90. data/.travis.yml +0 -31
  91. data/appveyor.yml +0 -22
  92. data/gemfiles/rails_6_0_beta.gemfile +0 -9
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../../helpers/arvm_test_utilities.rb"
4
- require_relative "../../helpers/arvm_test_models.rb"
5
- require_relative '../../helpers/viewmodel_spec_helpers.rb'
3
+ require_relative '../../helpers/arvm_test_utilities'
4
+ require_relative '../../helpers/arvm_test_models'
5
+ require_relative '../../helpers/viewmodel_spec_helpers'
6
6
 
7
- require "minitest/autorun"
7
+ require 'minitest/autorun'
8
8
  require 'minitest/unit'
9
9
 
10
10
  require 'rspec/expectations/minitest_integration'
11
11
 
12
- require "view_model/active_record"
12
+ require 'view_model/active_record'
13
13
 
14
14
  class ViewModel::AccessControlTest < ActiveSupport::TestCase
15
15
  include ARVMTestUtilities
@@ -55,103 +55,103 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
55
55
  end
56
56
 
57
57
  def test_visible_if
58
- TestAccessControl.visible_if!("car is visible1") do
59
- view.car == "visible1"
58
+ TestAccessControl.visible_if!('car is visible1') do
59
+ view.car == 'visible1'
60
60
  end
61
61
 
62
- TestAccessControl.visible_if!("car is visible2") do
63
- view.car == "visible2"
62
+ TestAccessControl.visible_if!('car is visible2') do
63
+ view.car == 'visible2'
64
64
  end
65
65
 
66
- assert_serializes(ListView, List.create!(car: "visible1"))
67
- assert_serializes(ListView, List.create!(car: "visible2"))
68
- ex = refute_serializes(ListView, List.create!(car: "bad"), /none of the possible/)
66
+ assert_serializes(ListView, List.create!(car: 'visible1'))
67
+ assert_serializes(ListView, List.create!(car: 'visible2'))
68
+ ex = refute_serializes(ListView, List.create!(car: 'bad'), /none of the possible/)
69
69
  assert_equal(2, ex.reasons.count)
70
70
  end
71
71
 
72
72
  def test_visible_unless
73
- TestAccessControl.visible_if!("always") { true }
73
+ TestAccessControl.visible_if!('always') { true }
74
74
 
75
- TestAccessControl.visible_unless!("car is invisible") do
76
- view.car == "invisible"
75
+ TestAccessControl.visible_unless!('car is invisible') do
76
+ view.car == 'invisible'
77
77
  end
78
78
 
79
- assert_serializes(ListView, List.create!(car: "ok"))
80
- refute_serializes(ListView, List.create!(car: "invisible"), /not permitted.*car is invisible/)
79
+ assert_serializes(ListView, List.create!(car: 'ok'))
80
+ refute_serializes(ListView, List.create!(car: 'invisible'), /not permitted.*car is invisible/)
81
81
  end
82
82
 
83
83
  def test_editable_if
84
- TestAccessControl.visible_if!("always") { true }
84
+ TestAccessControl.visible_if!('always') { true }
85
85
 
86
- TestAccessControl.editable_if!("car is editable1") do
87
- view.car == "editable1"
86
+ TestAccessControl.editable_if!('car is editable1') do
87
+ view.car == 'editable1'
88
88
  end
89
89
 
90
- TestAccessControl.editable_if!("car is editable2") do
91
- view.car == "editable2"
90
+ TestAccessControl.editable_if!('car is editable2') do
91
+ view.car == 'editable2'
92
92
  end
93
93
 
94
- assert_deserializes(ListView, List.create!(car: "editable1")) { |v, _| v["car"] = "unchecked" }
95
- assert_deserializes(ListView, List.create!(car: "editable2")) { |v, _| v["car"] = "unchecked" }
96
- assert_deserializes(ListView, List.create!(car: "forbidden")) { |v, _| v["car"] = "forbidden" } # no change so permitted
97
- refute_deserializes(ListView, List.create!(car: "forbidden"), /none of the possible/) { |v, _| v["car"] = "unchecked" }
94
+ assert_deserializes(ListView, List.create!(car: 'editable1')) { |v, _| v['car'] = 'unchecked' }
95
+ assert_deserializes(ListView, List.create!(car: 'editable2')) { |v, _| v['car'] = 'unchecked' }
96
+ assert_deserializes(ListView, List.create!(car: 'forbidden')) { |v, _| v['car'] = 'forbidden' } # no change so permitted
97
+ refute_deserializes(ListView, List.create!(car: 'forbidden'), /none of the possible/) { |v, _| v['car'] = 'unchecked' }
98
98
  end
99
99
 
100
100
  def test_editable_unless
101
- TestAccessControl.visible_if!("always") { true }
102
- TestAccessControl.editable_if!("always") { true }
101
+ TestAccessControl.visible_if!('always') { true }
102
+ TestAccessControl.editable_if!('always') { true }
103
103
 
104
- TestAccessControl.editable_unless!("car is uneditable") do
105
- view.car == "uneditable"
104
+ TestAccessControl.editable_unless!('car is uneditable') do
105
+ view.car == 'uneditable'
106
106
  end
107
107
 
108
- assert_deserializes(ListView, List.create!(car: "ok")) { |v, _| v["car"] = "unchecked" }
109
- assert_deserializes(ListView, List.create!(car: "uneditable")) { |v, _| v["car"] = "uneditable" } # no change so permitted
110
- refute_deserializes(ListView, List.create!(car: "uneditable"), /car is uneditable/) { |v, _| v["car"] = "unchecked" }
108
+ assert_deserializes(ListView, List.create!(car: 'ok')) { |v, _| v['car'] = 'unchecked' }
109
+ assert_deserializes(ListView, List.create!(car: 'uneditable')) { |v, _| v['car'] = 'uneditable' } # no change so permitted
110
+ refute_deserializes(ListView, List.create!(car: 'uneditable'), /car is uneditable/) { |v, _| v['car'] = 'unchecked' }
111
111
  end
112
112
 
113
113
  def test_edit_valid_if
114
- TestAccessControl.visible_if!("always") { true }
114
+ TestAccessControl.visible_if!('always') { true }
115
115
 
116
- TestAccessControl.edit_valid_if!("car is validedit") do
117
- view.car == "validedit"
116
+ TestAccessControl.edit_valid_if!('car is validedit') do
117
+ view.car == 'validedit'
118
118
  end
119
119
 
120
- assert_deserializes(ListView, List.create!(car: "unchecked")) { |v, _| v["car"] = "validedit" }
121
- assert_deserializes(ListView, List.create!(car: "unmodified")) { |v, _| v["car"] = "unmodified" } # no change so permitted
122
- refute_deserializes(ListView, List.create!(car: "unchecked"), /none of the possible/) { |v, _| v["car"] = "bad" }
120
+ assert_deserializes(ListView, List.create!(car: 'unchecked')) { |v, _| v['car'] = 'validedit' }
121
+ assert_deserializes(ListView, List.create!(car: 'unmodified')) { |v, _| v['car'] = 'unmodified' } # no change so permitted
122
+ refute_deserializes(ListView, List.create!(car: 'unchecked'), /none of the possible/) { |v, _| v['car'] = 'bad' }
123
123
  end
124
124
 
125
125
  def test_edit_valid_unless
126
- TestAccessControl.visible_if!("always") { true }
127
- TestAccessControl.edit_valid_if!("always") { true }
128
- TestAccessControl.edit_valid_unless!("car is invalidedit") do
129
- view.car == "invalidedit"
126
+ TestAccessControl.visible_if!('always') { true }
127
+ TestAccessControl.edit_valid_if!('always') { true }
128
+ TestAccessControl.edit_valid_unless!('car is invalidedit') do
129
+ view.car == 'invalidedit'
130
130
  end
131
131
 
132
- assert_deserializes(ListView, List.create!(car: "unchecked")) { |v, _| v["car"] = "ok" }
133
- assert_deserializes(ListView, List.create!(car: "invalidedit")) { |v, _| v["car"] = "invalidedit" }
134
- refute_deserializes(ListView, List.create!(car: "unchecked"), /car is invalidedit/) { |v, _| v["car"] = "invalidedit" }
132
+ assert_deserializes(ListView, List.create!(car: 'unchecked')) { |v, _| v['car'] = 'ok' }
133
+ assert_deserializes(ListView, List.create!(car: 'invalidedit')) { |v, _| v['car'] = 'invalidedit' }
134
+ refute_deserializes(ListView, List.create!(car: 'unchecked'), /car is invalidedit/) { |v, _| v['car'] = 'invalidedit' }
135
135
  end
136
136
 
137
137
  def test_editable_and_edit_valid
138
- TestAccessControl.visible_if!("always") { true }
138
+ TestAccessControl.visible_if!('always') { true }
139
139
 
140
- TestAccessControl.editable_if!("original car permits") do
141
- view.car == "permitoriginal"
140
+ TestAccessControl.editable_if!('original car permits') do
141
+ view.car == 'permitoriginal'
142
142
  end
143
143
 
144
- TestAccessControl.edit_valid_if!("resulting car permits") do
145
- view.car == "permitresult"
144
+ TestAccessControl.edit_valid_if!('resulting car permits') do
145
+ view.car == 'permitresult'
146
146
  end
147
147
 
148
148
  # at least one valid
149
- assert_deserializes(ListView, List.create!(car: "permitoriginal")) { |v, _| v["car"] = "permitresult" }
150
- assert_deserializes(ListView, List.create!(car: "badoriginal")) { |v, _| v["car"] = "permitresult" }
151
- assert_deserializes(ListView, List.create!(car: "permitoriginal")) { |v, _| v["car"] = "badresult" }
149
+ assert_deserializes(ListView, List.create!(car: 'permitoriginal')) { |v, _| v['car'] = 'permitresult' }
150
+ assert_deserializes(ListView, List.create!(car: 'badoriginal')) { |v, _| v['car'] = 'permitresult' }
151
+ assert_deserializes(ListView, List.create!(car: 'permitoriginal')) { |v, _| v['car'] = 'badresult' }
152
152
 
153
153
  # no valid
154
- ex = refute_deserializes(ListView, List.create!(car: "badoriginal"), /none of the possible/) { |v, _| v["car"] = "badresult" }
154
+ ex = refute_deserializes(ListView, List.create!(car: 'badoriginal'), /none of the possible/) { |v, _| v['car'] = 'badresult' }
155
155
 
156
156
  assert_equal(2, ex.reasons.count)
157
157
  end
@@ -160,14 +160,14 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
160
160
  child_access_control = Class.new(ViewModel::AccessControl::Composed)
161
161
  child_access_control.include_from(TestAccessControl)
162
162
 
163
- TestAccessControl.visible_if!("car is ancestor") { view.car == "ancestor" }
164
- child_access_control.visible_if!("car is descendent") { view.car == "descendent" }
163
+ TestAccessControl.visible_if!('car is ancestor') { view.car == 'ancestor' }
164
+ child_access_control.visible_if!('car is descendent') { view.car == 'descendent' }
165
165
 
166
166
  s_ctx = ListView.new_serialize_context(access_control: child_access_control.new)
167
167
 
168
- assert_serializes(ListView, List.create!(car: "ancestor"), serialize_context: s_ctx)
169
- assert_serializes(ListView, List.create!(car: "descendent"), serialize_context: s_ctx)
170
- ex = refute_serializes(ListView, List.create!(car: "foreigner"), serialize_context: s_ctx)
168
+ assert_serializes(ListView, List.create!(car: 'ancestor'), serialize_context: s_ctx)
169
+ assert_serializes(ListView, List.create!(car: 'descendent'), serialize_context: s_ctx)
170
+ ex = refute_serializes(ListView, List.create!(car: 'foreigner'), serialize_context: s_ctx)
171
171
  assert_equal(2, ex.reasons.count)
172
172
  end
173
173
  end
@@ -243,7 +243,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
243
243
 
244
244
  child = root[attr]
245
245
 
246
- if (child_ref = child["_ref"])
246
+ if (child_ref = child['_ref'])
247
247
  child = refs[child_ref]
248
248
  end
249
249
 
@@ -255,189 +255,189 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
255
255
  end
256
256
 
257
257
  def test_visibility_from_root
258
- TestAccessControl.view "Tree1" do
259
- visible_if!("true") { true }
258
+ TestAccessControl.view 'Tree1' do
259
+ visible_if!('true') { true }
260
260
 
261
- root_children_visible_if!("root children visible") do
262
- view.val == "rule:visible_children"
261
+ root_children_visible_if!('root children visible') do
262
+ view.val == 'rule:visible_children'
263
263
  end
264
264
  end
265
265
 
266
- refute_serializes(Tree1View, make_tree("arbitrary parent", "invisible child"))
267
- assert_serializes(Tree1View, make_tree("rule:visible_children", "visible child"))
266
+ refute_serializes(Tree1View, make_tree('arbitrary parent', 'invisible child'))
267
+ assert_serializes(Tree1View, make_tree('rule:visible_children', 'visible child'))
268
268
 
269
269
  # nested root
270
- refute_serializes(Tree1View, make_tree("rule:visible_children", "visible child", "arbitrary parent", "invisible child"))
271
- assert_serializes(Tree1View, make_tree("rule:visible_children", "visible child", "rule:visible_children", "visible child"))
270
+ refute_serializes(Tree1View, make_tree('rule:visible_children', 'visible child', 'arbitrary parent', 'invisible child'))
271
+ assert_serializes(Tree1View, make_tree('rule:visible_children', 'visible child', 'rule:visible_children', 'visible child'))
272
272
  end
273
273
 
274
274
  def test_visibility_veto_from_root
275
- TestAccessControl.view "Tree1" do
276
- root_children_visible_unless!("root children invisible") do
277
- view.val == "rule:invisible_children"
275
+ TestAccessControl.view 'Tree1' do
276
+ root_children_visible_unless!('root children invisible') do
277
+ view.val == 'rule:invisible_children'
278
278
  end
279
279
  end
280
280
 
281
281
  TestAccessControl.always do
282
- visible_if!("true") { true }
282
+ visible_if!('true') { true }
283
283
  end
284
284
 
285
- assert_serializes(Tree1View, make_tree("arbitrary parent", "visible child"))
286
- refute_serializes(Tree1View, make_tree("rule:invisible_children", "invisible child"))
285
+ assert_serializes(Tree1View, make_tree('arbitrary parent', 'visible child'))
286
+ refute_serializes(Tree1View, make_tree('rule:invisible_children', 'invisible child'))
287
287
 
288
288
  # nested root
289
- assert_serializes(Tree1View, make_tree("arbitrary parent", "visible child", "arbitrary nested parent", "visible child"))
290
- refute_serializes(Tree1View, make_tree("arbitrary parent", "visible child", "rule:invisible_children", "invisible child"))
289
+ assert_serializes(Tree1View, make_tree('arbitrary parent', 'visible child', 'arbitrary nested parent', 'visible child'))
290
+ refute_serializes(Tree1View, make_tree('arbitrary parent', 'visible child', 'rule:invisible_children', 'invisible child'))
291
291
  end
292
292
 
293
293
  def test_editability_from_root
294
294
  TestAccessControl.always do
295
- visible_if!("always") { true }
295
+ visible_if!('always') { true }
296
296
  end
297
297
 
298
- TestAccessControl.view "Tree1" do
299
- editable_if!("true") { true }
298
+ TestAccessControl.view 'Tree1' do
299
+ editable_if!('true') { true }
300
300
 
301
- root_children_editable_if!("root children editable") do
302
- view.val == "rule:editable_children"
301
+ root_children_editable_if!('root children editable') do
302
+ view.val == 'rule:editable_children'
303
303
  end
304
304
  end
305
305
 
306
- refute_deserializes(Tree1View, make_tree("arbitrary parent", "uneditable child")) { |v, r|
307
- dig_tree(v, r, "tree2")["val"] = "change"
306
+ refute_deserializes(Tree1View, make_tree('arbitrary parent', 'uneditable child')) { |v, r|
307
+ dig_tree(v, r, 'tree2')['val'] = 'change'
308
308
  }
309
309
 
310
- assert_deserializes(Tree1View, make_tree("rule:editable_children", "editable child")) { |v, r|
311
- dig_tree(v, r, "tree2")["val"] = "change"
310
+ assert_deserializes(Tree1View, make_tree('rule:editable_children', 'editable child')) { |v, r|
311
+ dig_tree(v, r, 'tree2')['val'] = 'change'
312
312
  }
313
313
 
314
314
  # nested root
315
- refute_deserializes(Tree1View, make_tree("rule:editable_children", "editable child", "arbitrary parent", "uneditable child")) { |v, r|
316
- dig_tree(v, r, "tree2", "tree1", "tree2")["val"] = "change"
315
+ refute_deserializes(Tree1View, make_tree('rule:editable_children', 'editable child', 'arbitrary parent', 'uneditable child')) { |v, r|
316
+ dig_tree(v, r, 'tree2', 'tree1', 'tree2')['val'] = 'change'
317
317
  }
318
318
 
319
- assert_deserializes(Tree1View, make_tree("arbitrary parent", "uneditable child", "rule:editable_children", "editable child")) { |v, r|
320
- dig_tree(v, r, "tree2", "tree1", "tree2")["val"] = "change"
319
+ assert_deserializes(Tree1View, make_tree('arbitrary parent', 'uneditable child', 'rule:editable_children', 'editable child')) { |v, r|
320
+ dig_tree(v, r, 'tree2', 'tree1', 'tree2')['val'] = 'change'
321
321
  }
322
322
  end
323
323
 
324
324
  def test_editability_veto_from_root
325
325
  TestAccessControl.always do
326
- visible_if!("always") { true }
327
- editable_if!("always") { true }
326
+ visible_if!('always') { true }
327
+ editable_if!('always') { true }
328
328
  end
329
329
 
330
- TestAccessControl.view "Tree1" do
331
- root_children_editable_unless!("root children uneditable") do
332
- view.val == "rule:uneditable_children"
330
+ TestAccessControl.view 'Tree1' do
331
+ root_children_editable_unless!('root children uneditable') do
332
+ view.val == 'rule:uneditable_children'
333
333
  end
334
334
  end
335
335
 
336
- refute_deserializes(Tree1View, make_tree("rule:uneditable_children", "uneditable child")) { |v, r|
337
- dig_tree(v, r, "tree2")["val"] = "change"
336
+ refute_deserializes(Tree1View, make_tree('rule:uneditable_children', 'uneditable child')) { |v, r|
337
+ dig_tree(v, r, 'tree2')['val'] = 'change'
338
338
  }
339
339
 
340
- assert_deserializes(Tree1View, make_tree("arbitrary parent", "editable child")) { |v, r|
341
- dig_tree(v, r, "tree2")["val"] = "change"
340
+ assert_deserializes(Tree1View, make_tree('arbitrary parent', 'editable child')) { |v, r|
341
+ dig_tree(v, r, 'tree2')['val'] = 'change'
342
342
  }
343
343
 
344
344
  # nested root
345
- refute_deserializes(Tree1View, make_tree("arbitrary parent", "editable child", "rule:uneditable_children", "uneditable child")) { |v, r|
346
- dig_tree(v, r, "tree2", "tree1", "tree2")["val"] = "change"
345
+ refute_deserializes(Tree1View, make_tree('arbitrary parent', 'editable child', 'rule:uneditable_children', 'uneditable child')) { |v, r|
346
+ dig_tree(v, r, 'tree2', 'tree1', 'tree2')['val'] = 'change'
347
347
  }
348
348
 
349
- assert_deserializes(Tree1View, make_tree("rule:uneditable_children", "uneditable child", "arbitrary parent", "editable child")) { |v, r|
350
- dig_tree(v, r, "tree2", "tree1", "tree2")["val"] = "change"
349
+ assert_deserializes(Tree1View, make_tree('rule:uneditable_children', 'uneditable child', 'arbitrary parent', 'editable child')) { |v, r|
350
+ dig_tree(v, r, 'tree2', 'tree1', 'tree2')['val'] = 'change'
351
351
  }
352
352
  end
353
353
 
354
354
  def test_type_independence
355
- TestAccessControl.view "Tree1" do
356
- visible_if!("tree1 visible") do
357
- view.val == "tree1visible"
355
+ TestAccessControl.view 'Tree1' do
356
+ visible_if!('tree1 visible') do
357
+ view.val == 'tree1visible'
358
358
  end
359
359
  end
360
360
 
361
- TestAccessControl.view "Tree2" do
362
- visible_if!("tree2 visible") do
363
- view.val == "tree2visible"
361
+ TestAccessControl.view 'Tree2' do
362
+ visible_if!('tree2 visible') do
363
+ view.val == 'tree2visible'
364
364
  end
365
365
  end
366
366
 
367
- refute_serializes(Tree1View, make_tree("tree1invisible", "tree2visible"))
368
- assert_serializes(Tree1View, make_tree("tree1visible", "tree2visible"))
369
- refute_serializes(Tree1View, make_tree("tree1visible", "tree2invisible"))
367
+ refute_serializes(Tree1View, make_tree('tree1invisible', 'tree2visible'))
368
+ assert_serializes(Tree1View, make_tree('tree1visible', 'tree2visible'))
369
+ refute_serializes(Tree1View, make_tree('tree1visible', 'tree2invisible'))
370
370
  end
371
371
 
372
372
  def test_visibility_always_composition
373
- TestAccessControl.view "Tree1" do
374
- visible_if!("tree1 visible") do
375
- view.val == "tree1visible"
373
+ TestAccessControl.view 'Tree1' do
374
+ visible_if!('tree1 visible') do
375
+ view.val == 'tree1visible'
376
376
  end
377
377
  end
378
378
 
379
379
  TestAccessControl.always do
380
- visible_if!("tree2 visible") do
381
- view.val == "alwaysvisible"
380
+ visible_if!('tree2 visible') do
381
+ view.val == 'alwaysvisible'
382
382
  end
383
383
  end
384
384
 
385
- refute_serializes(Tree1View, Tree1.create(val: "bad"))
386
- assert_serializes(Tree1View, Tree1.create(val: "tree1visible"))
387
- assert_serializes(Tree1View, Tree1.create(val: "alwaysvisible"))
385
+ refute_serializes(Tree1View, Tree1.create(val: 'bad'))
386
+ assert_serializes(Tree1View, Tree1.create(val: 'tree1visible'))
387
+ assert_serializes(Tree1View, Tree1.create(val: 'alwaysvisible'))
388
388
  end
389
389
 
390
390
  def test_editability_always_composition
391
- TestAccessControl.view "Tree1" do
392
- editable_if!("editable1") { view.val == "editable1" }
393
- edit_valid_if!("editvalid1") { view.val == "editvalid1" }
391
+ TestAccessControl.view 'Tree1' do
392
+ editable_if!('editable1') { view.val == 'editable1' }
393
+ edit_valid_if!('editvalid1') { view.val == 'editvalid1' }
394
394
  end
395
395
 
396
396
  TestAccessControl.always do
397
- editable_if!("editable2") { view.val == "editable2" }
398
- edit_valid_if!("editvalid2") { view.val == "editvalid2" }
397
+ editable_if!('editable2') { view.val == 'editable2' }
398
+ edit_valid_if!('editvalid2') { view.val == 'editvalid2' }
399
399
 
400
- visible_if!("always") { true }
400
+ visible_if!('always') { true }
401
401
  end
402
402
 
403
- refute_deserializes(Tree1View, Tree1.create!(val: "bad")) { |v, _| v["val"] = "alsobad" }
403
+ refute_deserializes(Tree1View, Tree1.create!(val: 'bad')) { |v, _| v['val'] = 'alsobad' }
404
404
 
405
- assert_deserializes(Tree1View, Tree1.create!(val: "editable1")) { |v, _| v["val"] = "unchecked" }
406
- assert_deserializes(Tree1View, Tree1.create!(val: "editable2")) { |v, _| v["val"] = "unchecked" }
405
+ assert_deserializes(Tree1View, Tree1.create!(val: 'editable1')) { |v, _| v['val'] = 'unchecked' }
406
+ assert_deserializes(Tree1View, Tree1.create!(val: 'editable2')) { |v, _| v['val'] = 'unchecked' }
407
407
 
408
- assert_deserializes(Tree1View, Tree1.create!(val: "unchecked")) { |v, _| v["val"] = "editvalid1" }
409
- assert_deserializes(Tree1View, Tree1.create!(val: "unchecked")) { |v, _| v["val"] = "editvalid2" }
408
+ assert_deserializes(Tree1View, Tree1.create!(val: 'unchecked')) { |v, _| v['val'] = 'editvalid1' }
409
+ assert_deserializes(Tree1View, Tree1.create!(val: 'unchecked')) { |v, _| v['val'] = 'editvalid2' }
410
410
  end
411
411
 
412
412
  def test_ancestry
413
- TestAccessControl.view "Tree1" do
414
- visible_if!("parent tree1") { view.val == "parenttree1" }
413
+ TestAccessControl.view 'Tree1' do
414
+ visible_if!('parent tree1') { view.val == 'parenttree1' }
415
415
  end
416
416
 
417
417
  TestAccessControl.always do
418
- visible_if!("parent always") { view.val == "parentalways" }
418
+ visible_if!('parent always') { view.val == 'parentalways' }
419
419
  end
420
420
 
421
421
  # Child must be set up after parent is fully defined
422
422
  child_access_control = Class.new(ViewModel::AccessControl::Tree)
423
423
  child_access_control.include_from(TestAccessControl)
424
424
 
425
- child_access_control.view "Tree1" do
426
- visible_if!("child tree1") { view.val == "childtree1" }
425
+ child_access_control.view 'Tree1' do
426
+ visible_if!('child tree1') { view.val == 'childtree1' }
427
427
  end
428
428
 
429
429
  child_access_control.always do
430
- visible_if!("child always") { view.val == "childalways" }
430
+ visible_if!('child always') { view.val == 'childalways' }
431
431
  end
432
432
 
433
433
  s_ctx = Tree1View.new_serialize_context(access_control: child_access_control.new)
434
434
 
435
- refute_serializes(Tree1View, Tree1.create!(val: "bad"), serialize_context: s_ctx)
435
+ refute_serializes(Tree1View, Tree1.create!(val: 'bad'), serialize_context: s_ctx)
436
436
 
437
- assert_serializes(Tree1View, Tree1.create!(val: "parenttree1"), serialize_context: s_ctx)
438
- assert_serializes(Tree1View, Tree1.create!(val: "parentalways"), serialize_context: s_ctx)
439
- assert_serializes(Tree1View, Tree1.create!(val: "childtree1"), serialize_context: s_ctx)
440
- assert_serializes(Tree1View, Tree1.create!(val: "childalways"), serialize_context: s_ctx)
437
+ assert_serializes(Tree1View, Tree1.create!(val: 'parenttree1'), serialize_context: s_ctx)
438
+ assert_serializes(Tree1View, Tree1.create!(val: 'parentalways'), serialize_context: s_ctx)
439
+ assert_serializes(Tree1View, Tree1.create!(val: 'childtree1'), serialize_context: s_ctx)
440
+ assert_serializes(Tree1View, Tree1.create!(val: 'childalways'), serialize_context: s_ctx)
441
441
  end
442
442
  end
443
443
 
@@ -574,7 +574,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
574
574
  model_class.new(
575
575
  name: 'a',
576
576
  children: [child_model_class.new(name: 'x', position: 1),
577
- child_model_class.new(name: 'y', position: 2)])
577
+ child_model_class.new(name: 'y', position: 2),])
578
578
  end
579
579
 
580
580
  it 'records new children' do
@@ -619,7 +619,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
619
619
 
620
620
  new_child = vm.children.detect { |c| c.name == 'b' }
621
621
  c_changes = ctx.valid_edit_changes(new_child.to_reference)
622
- assert_changes_match(c_changes, n:true, att: ['name'])
622
+ assert_changes_match(c_changes, n: true, att: ['name'])
623
623
 
624
624
  oc_changes = ctx.valid_edit_changes(
625
625
  ViewModel::Reference.new(child_viewmodel_class, replaced_child.id))