iknow_view_models 3.1.6 → 3.2.2

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 (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 +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 +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 +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 +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,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))