iknow_view_models 3.2.0 → 3.2.1

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +13 -0
  3. data/Appraisals +6 -6
  4. data/Rakefile +5 -5
  5. data/gemfiles/rails_5_2.gemfile +5 -5
  6. data/gemfiles/rails_6_0.gemfile +5 -5
  7. data/iknow_view_models.gemspec +40 -39
  8. data/lib/iknow_view_models.rb +9 -7
  9. data/lib/iknow_view_models/version.rb +1 -1
  10. data/lib/view_model.rb +17 -14
  11. data/lib/view_model/access_control.rb +5 -2
  12. data/lib/view_model/access_control/composed.rb +10 -9
  13. data/lib/view_model/access_control/open.rb +2 -0
  14. data/lib/view_model/access_control/read_only.rb +2 -0
  15. data/lib/view_model/access_control/tree.rb +11 -6
  16. data/lib/view_model/access_control_error.rb +4 -1
  17. data/lib/view_model/active_record.rb +12 -11
  18. data/lib/view_model/active_record/association_data.rb +2 -1
  19. data/lib/view_model/active_record/association_manipulation.rb +6 -4
  20. data/lib/view_model/active_record/cache.rb +4 -2
  21. data/lib/view_model/active_record/collection_nested_controller.rb +3 -3
  22. data/lib/view_model/active_record/controller_base.rb +4 -1
  23. data/lib/view_model/active_record/nested_controller_base.rb +1 -0
  24. data/lib/view_model/active_record/update_context.rb +8 -6
  25. data/lib/view_model/active_record/update_data.rb +32 -30
  26. data/lib/view_model/active_record/update_operation.rb +17 -13
  27. data/lib/view_model/active_record/visitor.rb +0 -1
  28. data/lib/view_model/after_transaction_runner.rb +0 -1
  29. data/lib/view_model/callbacks.rb +3 -1
  30. data/lib/view_model/controller.rb +13 -3
  31. data/lib/view_model/deserialization_error.rb +15 -12
  32. data/lib/view_model/error.rb +12 -10
  33. data/lib/view_model/error_view.rb +3 -1
  34. data/lib/view_model/migration/no_path_error.rb +1 -0
  35. data/lib/view_model/migration/one_way_error.rb +1 -0
  36. data/lib/view_model/migration/unspecified_version_error.rb +1 -0
  37. data/lib/view_model/record.rb +11 -13
  38. data/lib/view_model/reference.rb +3 -1
  39. data/lib/view_model/references.rb +8 -5
  40. data/lib/view_model/registry.rb +1 -1
  41. data/lib/view_model/schemas.rb +9 -4
  42. data/lib/view_model/serialization_error.rb +4 -1
  43. data/lib/view_model/serialize_context.rb +4 -4
  44. data/lib/view_model/test_helpers.rb +8 -3
  45. data/lib/view_model/test_helpers/arvm_builder.rb +19 -14
  46. data/lib/view_model/traversal_context.rb +2 -1
  47. data/test/.rubocop.yml +14 -0
  48. data/test/helpers/arvm_test_models.rb +12 -9
  49. data/test/helpers/arvm_test_utilities.rb +5 -3
  50. data/test/helpers/controller_test_helpers.rb +31 -29
  51. data/test/helpers/match_enumerator.rb +1 -0
  52. data/test/helpers/query_logging.rb +2 -1
  53. data/test/helpers/test_access_control.rb +5 -3
  54. data/test/helpers/viewmodel_spec_helpers.rb +21 -20
  55. data/test/unit/view_model/access_control_test.rb +144 -144
  56. data/test/unit/view_model/active_record/alias_test.rb +15 -13
  57. data/test/unit/view_model/active_record/belongs_to_test.rb +40 -39
  58. data/test/unit/view_model/active_record/cache_test.rb +27 -26
  59. data/test/unit/view_model/active_record/cloner_test.rb +67 -63
  60. data/test/unit/view_model/active_record/controller_test.rb +37 -38
  61. data/test/unit/view_model/active_record/counter_test.rb +10 -9
  62. data/test/unit/view_model/active_record/customization_test.rb +59 -58
  63. data/test/unit/view_model/active_record/has_many_test.rb +112 -111
  64. data/test/unit/view_model/active_record/has_many_through_poly_test.rb +15 -14
  65. data/test/unit/view_model/active_record/has_many_through_test.rb +33 -38
  66. data/test/unit/view_model/active_record/has_one_test.rb +37 -36
  67. data/test/unit/view_model/active_record/migration_test.rb +13 -13
  68. data/test/unit/view_model/active_record/namespacing_test.rb +19 -17
  69. data/test/unit/view_model/active_record/poly_test.rb +44 -45
  70. data/test/unit/view_model/active_record/shared_test.rb +30 -28
  71. data/test/unit/view_model/active_record/version_test.rb +9 -7
  72. data/test/unit/view_model/active_record_test.rb +72 -72
  73. data/test/unit/view_model/callbacks_test.rb +19 -15
  74. data/test/unit/view_model/controller_test.rb +4 -2
  75. data/test/unit/view_model/record_test.rb +92 -97
  76. data/test/unit/view_model/traversal_context_test.rb +4 -5
  77. data/test/unit/view_model_test.rb +18 -16
  78. metadata +7 -5
@@ -14,6 +14,7 @@ module MiniTest::Assertions
14
14
 
15
15
  def result
16
16
  return false unless @actual.respond_to? :to_a
17
+
17
18
  @extra_items = difference_between_enumerators(@actual, @expected)
18
19
  @missing_items = difference_between_enumerators(@expected, @actual)
19
20
  @extra_items.empty? & @missing_items.empty?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Test mixin that allows queries executed in a block to be introspected.
2
4
  #
3
5
  # Code run within a `log_queries` block will collect data. Collected data is
@@ -9,7 +11,6 @@
9
11
  require 'active_support/subscriber'
10
12
 
11
13
  module QueryLogging
12
-
13
14
  # ActiveRecord integration
14
15
  class QueryLogger < ActiveSupport::Subscriber
15
16
  @log = false
@@ -1,5 +1,6 @@
1
- require "iknow_view_models"
1
+ # frozen_string_literal: true
2
2
 
3
+ require 'iknow_view_models'
3
4
 
4
5
  class TestAccessControl < ViewModel::AccessControl
5
6
  attr_accessor :editable_checks, :visible_checks
@@ -41,13 +42,14 @@ class TestAccessControl < ViewModel::AccessControl
41
42
  def valid_edit_changes(ref)
42
43
  all = all_valid_edit_changes(ref)
43
44
  raise "Expected single change for ref '#{ref}'; found #{all}" unless all.size == 1
45
+
44
46
  all.first
45
47
  end
46
48
 
47
49
  def all_valid_edit_changes(ref)
48
50
  @valid_edit_checks
49
- .select { | cref, _changes| cref == ref }
50
- .map { |_cref, changes| changes }
51
+ .select { |cref, _changes| cref == ref }
52
+ .map { |_cref, changes| changes }
51
53
  end
52
54
 
53
55
  def was_edited?(ref)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'view_model'
2
4
  require 'view_model/test_helpers'
3
5
 
@@ -77,7 +79,7 @@ module ViewModelSpecHelpers
77
79
  ViewModel::TestHelpers::ARVMBuilder::Spec.new(
78
80
  schema: ->(t) { t.string :name },
79
81
  model: ->(m) {},
80
- viewmodel: ->(v) { root!; attribute :name }
82
+ viewmodel: ->(_v) { root!; attribute :name },
81
83
  )
82
84
  end
83
85
 
@@ -85,7 +87,7 @@ module ViewModelSpecHelpers
85
87
  ViewModel::TestHelpers::ARVMBuilder::Spec.new(
86
88
  schema: ->(t) { t.string :name },
87
89
  model: ->(m) {},
88
- viewmodel: ->(v) { attribute :name }
90
+ viewmodel: ->(_v) { attribute :name },
89
91
  )
90
92
  end
91
93
 
@@ -125,7 +127,7 @@ module ViewModelSpecHelpers
125
127
  end
126
128
 
127
129
  def child_attributes
128
- super.merge(model: ->(m) { has_one :model, inverse_of: :child })
130
+ super.merge(model: ->(_m) { has_one :model, inverse_of: :child })
129
131
  end
130
132
 
131
133
  # parent depends on child, ensure it's touched first
@@ -208,7 +210,7 @@ module ViewModelSpecHelpers
208
210
  extend ActiveSupport::Concern
209
211
  include ViewModelSpecHelpers::ParentAndBelongsToChild
210
212
  def child_attributes
211
- super.merge(viewmodel: ->(v) { root! })
213
+ super.merge(viewmodel: ->(_v) { root! })
212
214
  end
213
215
  end
214
216
 
@@ -222,11 +224,11 @@ module ViewModelSpecHelpers
222
224
  t.string :name
223
225
  t.integer :next_id
224
226
  },
225
- model: ->(m) {
227
+ model: ->(_m) {
226
228
  belongs_to :next, class_name: self.name, inverse_of: :previous, dependent: :destroy
227
229
  has_one :previous, class_name: self.name, foreign_key: :next_id, inverse_of: :next
228
230
  },
229
- viewmodel: ->(v) {
231
+ viewmodel: ->(_v) {
230
232
  # Not a root
231
233
  association :next
232
234
  attribute :name
@@ -245,15 +247,15 @@ module ViewModelSpecHelpers
245
247
  def model_attributes
246
248
  f = subject_association_features
247
249
  super.merge(
248
- model: ->(m) { has_one :child, inverse_of: :model, dependent: :destroy },
249
- viewmodel: ->(v) { association :child, **f }
250
+ model: ->(_m) { has_one :child, inverse_of: :model, dependent: :destroy },
251
+ viewmodel: ->(_v) { association :child, **f },
250
252
  )
251
253
  end
252
254
 
253
255
  def child_attributes
254
256
  super.merge(
255
257
  schema: ->(t) { t.references :model, foreign_key: true },
256
- model: ->(m) { belongs_to :model, inverse_of: :child }
258
+ model: ->(_m) { belongs_to :model, inverse_of: :child },
257
259
  )
258
260
  end
259
261
 
@@ -272,7 +274,7 @@ module ViewModelSpecHelpers
272
274
  extend ActiveSupport::Concern
273
275
  include ViewModelSpecHelpers::ParentAndHasOneChild
274
276
  def child_attributes
275
- super.merge(viewmodel: ->(v) { root! })
277
+ super.merge(viewmodel: ->(_v) { root! })
276
278
  end
277
279
  end
278
280
 
@@ -283,15 +285,15 @@ module ViewModelSpecHelpers
283
285
  def model_attributes
284
286
  f = subject_association_features
285
287
  super.merge(
286
- model: ->(m) { has_many :children, inverse_of: :model, dependent: :destroy },
287
- viewmodel: ->(v) { association :children, **f }
288
+ model: ->(_m) { has_many :children, inverse_of: :model, dependent: :destroy },
289
+ viewmodel: ->(_v) { association :children, **f },
288
290
  )
289
291
  end
290
292
 
291
293
  def child_attributes
292
294
  super.merge(
293
295
  schema: ->(t) { t.references :model, foreign_key: true },
294
- model: ->(m) { belongs_to :model, inverse_of: :children }
296
+ model: ->(_m) { belongs_to :model, inverse_of: :children },
295
297
  )
296
298
  end
297
299
 
@@ -310,7 +312,7 @@ module ViewModelSpecHelpers
310
312
  extend ActiveSupport::Concern
311
313
  include ViewModelSpecHelpers::ParentAndHasManyChildren
312
314
  def child_attributes
313
- super.merge(viewmodel: ->(v) { root! })
315
+ super.merge(viewmodel: ->(_v) { root! })
314
316
  end
315
317
  end
316
318
 
@@ -336,12 +338,11 @@ module ViewModelSpecHelpers
336
338
  table = model.table_name
337
339
  model.connection.execute <<-SQL
338
340
  ALTER TABLE #{table} ADD CONSTRAINT #{table}_unique_on_model_and_position UNIQUE(model_id, position) DEFERRABLE INITIALLY DEFERRED
339
- SQL
341
+ SQL
340
342
  end
341
343
  end
342
344
  end
343
345
 
344
-
345
346
  module ParentAndExternalSharedChild
346
347
  extend ActiveSupport::Concern
347
348
  include ViewModelSpecHelpers::ParentAndSharedBelongsToChild
@@ -358,15 +359,15 @@ module ViewModelSpecHelpers
358
359
  def model_attributes
359
360
  f = subject_association_features
360
361
  super.merge(
361
- model: ->(m) { has_many :model_children, inverse_of: :model, dependent: :destroy },
362
- viewmodel: ->(v) { association :children, through: :model_children, through_order_attr: :position, **f }
362
+ model: ->(_m) { has_many :model_children, inverse_of: :model, dependent: :destroy },
363
+ viewmodel: ->(_v) { association :children, through: :model_children, through_order_attr: :position, **f },
363
364
  )
364
365
  end
365
366
 
366
367
  def child_attributes
367
368
  super.merge(
368
- model: ->(m) { has_many :model_children, inverse_of: :child, dependent: :destroy },
369
- viewmodel: ->(v) { root! }
369
+ model: ->(_m) { has_many :model_children, inverse_of: :child, dependent: :destroy },
370
+ viewmodel: ->(_v) { root! },
370
371
  )
371
372
  end
372
373
 
@@ -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))