iknow_view_models 2.8.4

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 (92) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +115 -0
  3. data/.gitignore +36 -0
  4. data/.travis.yml +31 -0
  5. data/Appraisals +9 -0
  6. data/Gemfile +19 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +19 -0
  9. data/Rakefile +21 -0
  10. data/appveyor.yml +22 -0
  11. data/gemfiles/rails_5_2.gemfile +15 -0
  12. data/gemfiles/rails_6_0_beta.gemfile +15 -0
  13. data/iknow_view_models.gemspec +49 -0
  14. data/lib/iknow_view_models.rb +12 -0
  15. data/lib/iknow_view_models/railtie.rb +8 -0
  16. data/lib/iknow_view_models/version.rb +5 -0
  17. data/lib/view_model.rb +333 -0
  18. data/lib/view_model/access_control.rb +154 -0
  19. data/lib/view_model/access_control/composed.rb +216 -0
  20. data/lib/view_model/access_control/open.rb +13 -0
  21. data/lib/view_model/access_control/read_only.rb +13 -0
  22. data/lib/view_model/access_control/tree.rb +264 -0
  23. data/lib/view_model/access_control_error.rb +10 -0
  24. data/lib/view_model/active_record.rb +383 -0
  25. data/lib/view_model/active_record/association_data.rb +178 -0
  26. data/lib/view_model/active_record/association_manipulation.rb +389 -0
  27. data/lib/view_model/active_record/cache.rb +265 -0
  28. data/lib/view_model/active_record/cache/cacheable_view.rb +51 -0
  29. data/lib/view_model/active_record/cloner.rb +113 -0
  30. data/lib/view_model/active_record/collection_nested_controller.rb +100 -0
  31. data/lib/view_model/active_record/controller.rb +77 -0
  32. data/lib/view_model/active_record/controller_base.rb +185 -0
  33. data/lib/view_model/active_record/nested_controller_base.rb +93 -0
  34. data/lib/view_model/active_record/singular_nested_controller.rb +34 -0
  35. data/lib/view_model/active_record/update_context.rb +252 -0
  36. data/lib/view_model/active_record/update_data.rb +749 -0
  37. data/lib/view_model/active_record/update_operation.rb +810 -0
  38. data/lib/view_model/active_record/visitor.rb +77 -0
  39. data/lib/view_model/after_transaction_runner.rb +29 -0
  40. data/lib/view_model/callbacks.rb +219 -0
  41. data/lib/view_model/changes.rb +62 -0
  42. data/lib/view_model/config.rb +29 -0
  43. data/lib/view_model/controller.rb +142 -0
  44. data/lib/view_model/deserialization_error.rb +437 -0
  45. data/lib/view_model/deserialize_context.rb +16 -0
  46. data/lib/view_model/error.rb +191 -0
  47. data/lib/view_model/error_view.rb +35 -0
  48. data/lib/view_model/record.rb +367 -0
  49. data/lib/view_model/record/attribute_data.rb +48 -0
  50. data/lib/view_model/reference.rb +31 -0
  51. data/lib/view_model/references.rb +48 -0
  52. data/lib/view_model/registry.rb +73 -0
  53. data/lib/view_model/schemas.rb +45 -0
  54. data/lib/view_model/serialization_error.rb +10 -0
  55. data/lib/view_model/serialize_context.rb +118 -0
  56. data/lib/view_model/test_helpers.rb +103 -0
  57. data/lib/view_model/test_helpers/arvm_builder.rb +111 -0
  58. data/lib/view_model/traversal_context.rb +126 -0
  59. data/lib/view_model/utils.rb +24 -0
  60. data/lib/view_model/utils/collections.rb +49 -0
  61. data/test/helpers/arvm_test_models.rb +59 -0
  62. data/test/helpers/arvm_test_utilities.rb +187 -0
  63. data/test/helpers/callback_tracer.rb +27 -0
  64. data/test/helpers/controller_test_helpers.rb +270 -0
  65. data/test/helpers/match_enumerator.rb +58 -0
  66. data/test/helpers/query_logging.rb +71 -0
  67. data/test/helpers/test_access_control.rb +56 -0
  68. data/test/helpers/viewmodel_spec_helpers.rb +326 -0
  69. data/test/unit/view_model/access_control_test.rb +769 -0
  70. data/test/unit/view_model/active_record/alias_test.rb +35 -0
  71. data/test/unit/view_model/active_record/belongs_to_test.rb +376 -0
  72. data/test/unit/view_model/active_record/cache_test.rb +351 -0
  73. data/test/unit/view_model/active_record/cloner_test.rb +313 -0
  74. data/test/unit/view_model/active_record/controller_test.rb +561 -0
  75. data/test/unit/view_model/active_record/counter_test.rb +80 -0
  76. data/test/unit/view_model/active_record/customization_test.rb +388 -0
  77. data/test/unit/view_model/active_record/has_many_test.rb +957 -0
  78. data/test/unit/view_model/active_record/has_many_through_poly_test.rb +269 -0
  79. data/test/unit/view_model/active_record/has_many_through_test.rb +736 -0
  80. data/test/unit/view_model/active_record/has_one_test.rb +334 -0
  81. data/test/unit/view_model/active_record/namespacing_test.rb +75 -0
  82. data/test/unit/view_model/active_record/optional_attribute_view_test.rb +58 -0
  83. data/test/unit/view_model/active_record/poly_test.rb +320 -0
  84. data/test/unit/view_model/active_record/shared_test.rb +285 -0
  85. data/test/unit/view_model/active_record/version_test.rb +121 -0
  86. data/test/unit/view_model/active_record_test.rb +542 -0
  87. data/test/unit/view_model/callbacks_test.rb +582 -0
  88. data/test/unit/view_model/deserialization_error/unique_violation_test.rb +73 -0
  89. data/test/unit/view_model/record_test.rb +524 -0
  90. data/test/unit/view_model/traversal_context_test.rb +371 -0
  91. data/test/unit/view_model_test.rb +62 -0
  92. metadata +490 -0
@@ -0,0 +1,371 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ require 'minitest/autorun'
5
+ require 'minitest/unit'
6
+ require 'minitest/hooks'
7
+
8
+ require_relative '../../helpers/match_enumerator.rb'
9
+ require_relative '../../helpers/arvm_test_utilities.rb'
10
+ require_relative '../../helpers/arvm_test_models.rb'
11
+ require_relative '../../helpers/viewmodel_spec_helpers.rb'
12
+
13
+ require 'view_model'
14
+ require 'view_model/record'
15
+
16
+ class ViewModel::TraversalContextTest < ActiveSupport::TestCase
17
+ include ARVMTestUtilities
18
+ extend Minitest::Spec::DSL
19
+
20
+ # Use a on-entry callback to ensure that views are visited with the expected
21
+ # local TraversalContext in various flows
22
+ ContextDetail = Value.new(:parent_ref, :parent_association, :root)
23
+
24
+ class ContextRecorder
25
+ include ViewModel::Callbacks
26
+ attr_reader :details
27
+
28
+ # Views are identified by their ref (type/id): this means that for the
29
+ # purposes of these tests, new models must all have an id specified.
30
+ def initialize
31
+ @details = {}
32
+ end
33
+
34
+ # record information after_visit: allows id of new models to be established
35
+ after_visit do
36
+ ref = view.to_reference
37
+ raise RuntimeError.new('Visited twice') if details.has_key?(ref)
38
+ details[ref] = ContextDetail.new(
39
+ context.parent_viewmodel&.to_reference,
40
+ context.parent_association,
41
+ context.root?)
42
+ end
43
+ end
44
+
45
+ let(:vm) { create_viewmodel! }
46
+
47
+ let(:context_recorder) { ContextRecorder.new }
48
+
49
+ # Set up serialization and deserialization helpers to use the recording callback
50
+ def vm_serialize_context(viewmodel_class, **args)
51
+ viewmodel_class.new_serialize_context(callbacks: [context_recorder], **args)
52
+ end
53
+
54
+ def vm_deserialize_context(viewmodel_class, **args)
55
+ viewmodel_class.new_deserialize_context(callbacks: [context_recorder], **args)
56
+ end
57
+
58
+ def serialize(view, serialize_context: vm_serialize_context(view.class))
59
+ super(view, serialize_context: serialize_context)
60
+ end
61
+
62
+ def serialize_with_references(view, serialize_context: vm_serialize_context(view.class))
63
+ super(view, serialize_context: serialize_context)
64
+ end
65
+
66
+ # use `alter_by_view` to test deserialization: only override the deserialize_context
67
+ def alter_by_view!(vm_class, model,
68
+ deserialize_context: vm_deserialize_context(vm_class),
69
+ **args,
70
+ &block)
71
+ super(vm_class, model, deserialize_context: deserialize_context, **args, &block)
72
+ end
73
+
74
+ module TraversalBehaviour
75
+ extend ActiveSupport::Concern
76
+ include Minitest::Hooks
77
+
78
+ def assert_traversal_matches(expected_details, recorded_details)
79
+ value(recorded_details.keys).must_contain_exactly(expected_details.keys)
80
+
81
+ recorded_details.each do |model_id, recorded_detail|
82
+ value(recorded_detail).must_equal(expected_details[model_id])
83
+ end
84
+ end
85
+
86
+ # Helpers to manipulate alter_by_view view hashes. Assumes that the test
87
+ # models have no more than one shared association, and if present it is the
88
+ # one under test.
89
+ def clear_subject_association(view, refs)
90
+ refs.clear if subject_association.shared?
91
+ view[subject_association_name] = subject_association.collection? ? [] : nil
92
+ end
93
+
94
+ def set_subject_association(view, refs, value)
95
+ if subject_association.shared?
96
+ refs.clear
97
+ value = convert_to_refs(refs, value)
98
+ end
99
+ view[subject_association_name] = value
100
+ end
101
+
102
+ def add_to_subject_association(view, refs, value)
103
+ if subject_association.shared?
104
+ value = convert_to_refs(refs, value)
105
+ end
106
+ view[subject_association_name] << value
107
+ end
108
+
109
+ def remove_from_subject_association(view, refs)
110
+ view[subject_association_name].reject! do |child|
111
+ if subject_association.shared?
112
+ ref = child[ViewModel::REFERENCE_ATTRIBUTE]
113
+ child = refs[ref]
114
+ end
115
+ match = yield(child)
116
+ if match && subject_association.shared?
117
+ refs.delete(ref)
118
+ end
119
+ match
120
+ end
121
+ end
122
+
123
+ def convert_to_refs(refs, value)
124
+ i = 0
125
+ ViewModel::Utils.map_one_or_many(value) do |v|
126
+ ref = "_child_ref_#{i += 1}"
127
+ refs[ref] = v
128
+ { ViewModel::REFERENCE_ATTRIBUTE => ref }
129
+ end
130
+ end
131
+ end
132
+
133
+ module BehavesLikeSerialization
134
+ extend ActiveSupport::Concern
135
+ include TraversalBehaviour
136
+ # requires :expected_parent_details, :expected_children_details
137
+
138
+ def self.included(base)
139
+ base.instance_eval do
140
+ it 'traverses as expected while serializing' do
141
+ serialize_with_references(vm)
142
+ expected = expected_parent_details.merge(expected_children_details)
143
+ assert_traversal_matches(expected, context_recorder.details)
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ module BehavesLikeDeserialization
150
+ extend ActiveSupport::Concern
151
+ include TraversalBehaviour
152
+ # requires
153
+ # :expected_parent_details, :expected_children_details
154
+ # :new_child_hash, :new_child_expected_details
155
+
156
+ def self.included(base)
157
+ base.instance_eval do
158
+ it 'traverses as expected while deserializing' do
159
+ alter_by_view!(viewmodel_class, vm.model) {}
160
+ expected = expected_parent_details.merge(expected_children_details)
161
+ assert_traversal_matches(expected, context_recorder.details)
162
+ end
163
+
164
+ it 'traverses as expected while clearing child(ren)' do
165
+ alter_by_view!(viewmodel_class, vm.model) do |view, refs|
166
+ clear_subject_association(view, refs)
167
+ end
168
+
169
+ expected = expected_parent_details
170
+ expected = expected.merge(expected_children_details) unless subject_association.shared?
171
+ assert_traversal_matches(expected, context_recorder.details)
172
+ end
173
+
174
+ it 'traverses as expected while replacing child(ren)' do
175
+ replacement = subject_association.collection? ? [new_child_hash] : new_child_hash
176
+
177
+ alter_by_view!(viewmodel_class, vm.model) do |view, refs|
178
+ set_subject_association(view, refs, replacement)
179
+ end
180
+
181
+ expected = expected_parent_details
182
+ expected = expected.merge(expected_children_details) unless subject_association.shared?
183
+ expected = expected.merge(new_child_expected_details)
184
+ assert_traversal_matches(expected, context_recorder.details)
185
+ end
186
+
187
+ it 'traverses as expected in replace_associated' do
188
+ ctx = vm_deserialize_context(viewmodel_class)
189
+ replacement = subject_association.collection? ? [new_child_hash] : new_child_hash
190
+ vm.replace_associated(subject_association_name, replacement, deserialize_context: ctx)
191
+
192
+ expected = expected_parent_details
193
+ expected = expected.merge(expected_children_details) unless subject_association.shared?
194
+ expected = expected.merge(new_child_expected_details)
195
+ assert_traversal_matches(expected, context_recorder.details)
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ module BehavesLikeCollectionDeserialization
202
+ extend ActiveSupport::Concern
203
+ include TraversalBehaviour
204
+
205
+ # requires :removed_child
206
+ def self.included(base)
207
+ base.instance_eval do
208
+ it 'traverses as expected when adding to children' do
209
+ alter_by_view!(viewmodel_class, vm.model) do |view, refs|
210
+ add_to_subject_association(view, refs, new_child_hash)
211
+ end
212
+
213
+ expected = expected_parent_details
214
+ .merge(expected_children_details)
215
+ .merge(new_child_expected_details)
216
+ assert_traversal_matches(expected, context_recorder.details)
217
+ end
218
+
219
+ it 'traverses as expected when removing from children' do
220
+ alter_by_view!(viewmodel_class, vm.model) do |view, refs|
221
+ remove_from_subject_association(view, refs) do |child|
222
+ child['id'] == removed_child.id
223
+ end
224
+ end
225
+
226
+ expected = expected_parent_details.merge(expected_children_details)
227
+ expected = expected.except(removed_child.to_reference) if subject_association.shared?
228
+ assert_traversal_matches(expected, context_recorder.details)
229
+ end
230
+
231
+ it 'traverses as expected in append_associated' do
232
+ ctx = vm_deserialize_context(viewmodel_class)
233
+ vm.append_associated(subject_association_name, [new_child_hash], deserialize_context: ctx)
234
+
235
+ expected = expected_parent_details.merge(new_child_expected_details)
236
+ assert_traversal_matches(expected, context_recorder.details)
237
+ end
238
+
239
+ it 'traverses as expected in delete_associated' do
240
+ ctx = vm_deserialize_context(viewmodel_class)
241
+ vm.delete_associated(subject_association_name, removed_child.id, deserialize_context: ctx)
242
+
243
+ expected = expected_parent_details
244
+ expected = expected.merge(removed_child_expected_details) unless subject_association.shared?
245
+ assert_traversal_matches(expected, context_recorder.details)
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ module BehavesLikeVisitor
252
+ def self.included(base)
253
+ base.instance_eval do
254
+ it 'traverses as expected while visiting' do
255
+ ViewModel::ActiveRecord::Visitor.new.visit(vm, context: vm_serialize_context(viewmodel_class))
256
+ expected = expected_parent_details.merge(expected_children_details)
257
+ assert_traversal_matches(expected, context_recorder.details)
258
+ end
259
+ end
260
+ end
261
+ end
262
+
263
+ # For each association type we want to make sure the traversal environment is
264
+ # as expected in every method of traversal.
265
+
266
+ let(:root_detail) { ContextDetail.new(nil, nil, true) }
267
+ let(:child_detail) do
268
+ if subject_association.shared?
269
+ root_detail
270
+ else
271
+ ContextDetail.new(vm.to_reference, subject_association_name, false)
272
+ end
273
+ end
274
+
275
+ let(:expected_parent_details) do
276
+ { vm.to_reference => root_detail }
277
+ end
278
+
279
+ let(:expected_children_details) do
280
+ children = {}
281
+ Array.wrap(vm.send(subject_association_name)).each do |child_vm|
282
+ children[child_vm.to_reference] = child_detail
283
+ end
284
+ children
285
+ end
286
+
287
+ before(:each) { expected_children_details }
288
+
289
+ let(:new_model) do
290
+ associated =
291
+ if subject_association.collection?
292
+ [child_model_class.new(name: 'b'), child_model_class.new(name: 'c')]
293
+ else
294
+ child_model_class.new(name: 'b')
295
+ end
296
+
297
+ model_class.new(name: 'a', subject_association_name => associated)
298
+ end
299
+
300
+ let(:new_child_id) { 9999 }
301
+ let(:new_child_ref) { ViewModel::Reference.new(child_viewmodel_class, new_child_id) }
302
+ let(:new_child_hash) do
303
+ {
304
+ '_type' => child_viewmodel_class.view_name,
305
+ 'id' => new_child_id,
306
+ '_new' => true,
307
+ 'name' => 'z',
308
+ }
309
+ end
310
+
311
+ let(:new_child_expected_details) do
312
+ { new_child_ref => child_detail }
313
+ end
314
+
315
+ let(:removed_child) do
316
+ Array.wrap(vm.send(subject_association_name)).first
317
+ end
318
+
319
+ let(:removed_child_expected_details) do
320
+ { removed_child.to_reference => child_detail }
321
+ end
322
+
323
+ describe 'with parent and belongs to child' do
324
+ include ViewModelSpecHelpers::ParentAndBelongsToChild
325
+
326
+ include BehavesLikeSerialization
327
+ include BehavesLikeDeserialization
328
+ include BehavesLikeVisitor
329
+ end
330
+
331
+ describe 'with parent and has_one child' do
332
+ include ViewModelSpecHelpers::ParentAndBelongsToChild
333
+
334
+ include BehavesLikeSerialization
335
+ include BehavesLikeDeserialization
336
+ include BehavesLikeVisitor
337
+ end
338
+
339
+ describe 'with parent and has_many children' do
340
+ include ViewModelSpecHelpers::ParentAndHasManyChildren
341
+
342
+ include BehavesLikeSerialization
343
+ include BehavesLikeDeserialization
344
+ include BehavesLikeCollectionDeserialization
345
+ include BehavesLikeVisitor
346
+ end
347
+
348
+ describe 'with parent and shared child' do
349
+ include ViewModelSpecHelpers::ParentAndSharedChild
350
+
351
+ include BehavesLikeSerialization
352
+ include BehavesLikeDeserialization
353
+ include BehavesLikeVisitor
354
+ end
355
+
356
+ describe 'with parent and has-many-through children' do
357
+ include ViewModelSpecHelpers::ParentAndHasManyThroughChildren
358
+ let(:new_model) do
359
+ model_class.new(name: 'a',
360
+ model_children: [
361
+ join_model_class.new(child: child_model_class.new(name: 'b')),
362
+ join_model_class.new(child: child_model_class.new(name: 'c')),
363
+ ])
364
+ end
365
+
366
+ include BehavesLikeSerialization
367
+ include BehavesLikeDeserialization
368
+ include BehavesLikeCollectionDeserialization
369
+ include BehavesLikeVisitor
370
+ end
371
+ end
@@ -0,0 +1,62 @@
1
+ require "bundler/setup"
2
+ Bundler.require
3
+
4
+ require "minitest/autorun"
5
+
6
+ class DefaultViewModel < ViewModel
7
+ self.view_name = 'DefaultViewModel'
8
+ attributes :foo, :bar
9
+ end
10
+
11
+ class TestViewModel < ViewModel
12
+ self.view_name = 'TestViewModel'
13
+
14
+ attributes :val
15
+ def serialize_view(json, **_options)
16
+ json.name val
17
+ end
18
+ end
19
+
20
+ class ViewModel::ActiveRecordTest < ActiveSupport::TestCase
21
+ def test_serialize
22
+ s = TestViewModel.new("a")
23
+ assert_equal(TestViewModel.serialize_to_hash(s),
24
+ { "name" => "a" })
25
+ end
26
+
27
+ def test_default_serialize
28
+ s = DefaultViewModel.new("a", 1)
29
+ assert_equal(TestViewModel.serialize_to_hash(s),
30
+ { "foo" => "a", "bar" => 1 })
31
+ end
32
+
33
+ def test_default_serialize_array
34
+ s = DefaultViewModel.new("a", [1,2])
35
+ assert_equal(TestViewModel.serialize_to_hash(s),
36
+ { "foo" => "a", "bar" => [1,2] })
37
+ end
38
+
39
+ def test_default_serialize_hash
40
+ s = DefaultViewModel.new("a", { "x" => "y" })
41
+ assert_equal(DefaultViewModel.serialize_to_hash(s),
42
+ { "foo" => "a", "bar" => { "x" => "y" } })
43
+ end
44
+
45
+ def test_default_serialize_empty_hash
46
+ s = DefaultViewModel.new("a", {})
47
+ assert_equal(DefaultViewModel.serialize_to_hash(s),
48
+ { "foo" => "a", "bar" => {} })
49
+ end
50
+
51
+ def test_default_serialize_viewmodel
52
+ s = DefaultViewModel.new("a", DefaultViewModel.new(1, 2))
53
+ assert_equal(DefaultViewModel.serialize_to_hash(s),
54
+ { "foo" => "a", "bar" => { "foo" => 1, "bar" => 2 } })
55
+ end
56
+
57
+ def test_default_serialize_array_of_viewmodel
58
+ s = DefaultViewModel.new("a", [TestViewModel.new("x"), TestViewModel.new("y")])
59
+ assert_equal(DefaultViewModel.serialize_to_hash(s),
60
+ { "foo" => "a", "bar" => [{"name" => "x"}, {"name" => "y"}] })
61
+ end
62
+ end
metadata ADDED
@@ -0,0 +1,490 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: iknow_view_models
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.8.4
5
+ platform: ruby
6
+ authors:
7
+ - iKnow Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-04-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: acts_as_manual_list
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: deep_preloader
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: iknow_cache
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: iknow_params
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: safe_values
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: keyword_builder
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: concurrent-ruby
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: jbuilder
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: json_schema
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: lazily
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: renum
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: appraisal
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: bundler
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: byebug
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
237
+ - !ruby/object:Gem::Dependency
238
+ name: method_source
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ type: :development
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - ">="
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
251
+ - !ruby/object:Gem::Dependency
252
+ name: minitest-hooks
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ">="
256
+ - !ruby/object:Gem::Version
257
+ version: '0'
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - ">="
263
+ - !ruby/object:Gem::Version
264
+ version: '0'
265
+ - !ruby/object:Gem::Dependency
266
+ name: pg
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - "~>"
270
+ - !ruby/object:Gem::Version
271
+ version: '0.18'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: '0.18'
279
+ - !ruby/object:Gem::Dependency
280
+ name: pry
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - ">="
291
+ - !ruby/object:Gem::Version
292
+ version: '0'
293
+ - !ruby/object:Gem::Dependency
294
+ name: rake
295
+ requirement: !ruby/object:Gem::Requirement
296
+ requirements:
297
+ - - ">="
298
+ - !ruby/object:Gem::Version
299
+ version: '0'
300
+ type: :development
301
+ prerelease: false
302
+ version_requirements: !ruby/object:Gem::Requirement
303
+ requirements:
304
+ - - ">="
305
+ - !ruby/object:Gem::Version
306
+ version: '0'
307
+ - !ruby/object:Gem::Dependency
308
+ name: rspec-expectations
309
+ requirement: !ruby/object:Gem::Requirement
310
+ requirements:
311
+ - - ">="
312
+ - !ruby/object:Gem::Version
313
+ version: '0'
314
+ type: :development
315
+ prerelease: false
316
+ version_requirements: !ruby/object:Gem::Requirement
317
+ requirements:
318
+ - - ">="
319
+ - !ruby/object:Gem::Version
320
+ version: '0'
321
+ - !ruby/object:Gem::Dependency
322
+ name: sqlite3
323
+ requirement: !ruby/object:Gem::Requirement
324
+ requirements:
325
+ - - ">="
326
+ - !ruby/object:Gem::Version
327
+ version: '0'
328
+ type: :development
329
+ prerelease: false
330
+ version_requirements: !ruby/object:Gem::Requirement
331
+ requirements:
332
+ - - ">="
333
+ - !ruby/object:Gem::Version
334
+ version: '0'
335
+ description: ''
336
+ email:
337
+ - edge@iknow.jp
338
+ executables: []
339
+ extensions: []
340
+ extra_rdoc_files: []
341
+ files:
342
+ - ".circleci/config.yml"
343
+ - ".gitignore"
344
+ - ".idea/codeStyleSettings.xml"
345
+ - ".travis.yml"
346
+ - Appraisals
347
+ - Gemfile
348
+ - LICENSE.txt
349
+ - README.md
350
+ - Rakefile
351
+ - appveyor.yml
352
+ - gemfiles/rails_5_2.gemfile
353
+ - gemfiles/rails_6_0_beta.gemfile
354
+ - iknow_view_models.gemspec
355
+ - lib/iknow_view_models.rb
356
+ - lib/iknow_view_models/railtie.rb
357
+ - lib/iknow_view_models/version.rb
358
+ - lib/view_model.rb
359
+ - lib/view_model/access_control.rb
360
+ - lib/view_model/access_control/composed.rb
361
+ - lib/view_model/access_control/open.rb
362
+ - lib/view_model/access_control/read_only.rb
363
+ - lib/view_model/access_control/tree.rb
364
+ - lib/view_model/access_control_error.rb
365
+ - lib/view_model/active_record.rb
366
+ - lib/view_model/active_record/association_data.rb
367
+ - lib/view_model/active_record/association_manipulation.rb
368
+ - lib/view_model/active_record/cache.rb
369
+ - lib/view_model/active_record/cache/cacheable_view.rb
370
+ - lib/view_model/active_record/cloner.rb
371
+ - lib/view_model/active_record/collection_nested_controller.rb
372
+ - lib/view_model/active_record/controller.rb
373
+ - lib/view_model/active_record/controller_base.rb
374
+ - lib/view_model/active_record/nested_controller_base.rb
375
+ - lib/view_model/active_record/singular_nested_controller.rb
376
+ - lib/view_model/active_record/update_context.rb
377
+ - lib/view_model/active_record/update_data.rb
378
+ - lib/view_model/active_record/update_operation.rb
379
+ - lib/view_model/active_record/visitor.rb
380
+ - lib/view_model/after_transaction_runner.rb
381
+ - lib/view_model/callbacks.rb
382
+ - lib/view_model/changes.rb
383
+ - lib/view_model/config.rb
384
+ - lib/view_model/controller.rb
385
+ - lib/view_model/deserialization_error.rb
386
+ - lib/view_model/deserialize_context.rb
387
+ - lib/view_model/error.rb
388
+ - lib/view_model/error_view.rb
389
+ - lib/view_model/record.rb
390
+ - lib/view_model/record/attribute_data.rb
391
+ - lib/view_model/reference.rb
392
+ - lib/view_model/references.rb
393
+ - lib/view_model/registry.rb
394
+ - lib/view_model/schemas.rb
395
+ - lib/view_model/serialization_error.rb
396
+ - lib/view_model/serialize_context.rb
397
+ - lib/view_model/test_helpers.rb
398
+ - lib/view_model/test_helpers/arvm_builder.rb
399
+ - lib/view_model/traversal_context.rb
400
+ - lib/view_model/utils.rb
401
+ - lib/view_model/utils/collections.rb
402
+ - test/config/database.yml
403
+ - test/helpers/arvm_test_models.rb
404
+ - test/helpers/arvm_test_utilities.rb
405
+ - test/helpers/callback_tracer.rb
406
+ - test/helpers/controller_test_helpers.rb
407
+ - test/helpers/match_enumerator.rb
408
+ - test/helpers/query_logging.rb
409
+ - test/helpers/test_access_control.rb
410
+ - test/helpers/viewmodel_spec_helpers.rb
411
+ - test/unit/view_model/access_control_test.rb
412
+ - test/unit/view_model/active_record/alias_test.rb
413
+ - test/unit/view_model/active_record/belongs_to_test.rb
414
+ - test/unit/view_model/active_record/cache_test.rb
415
+ - test/unit/view_model/active_record/cloner_test.rb
416
+ - test/unit/view_model/active_record/controller_test.rb
417
+ - test/unit/view_model/active_record/counter_test.rb
418
+ - test/unit/view_model/active_record/customization_test.rb
419
+ - test/unit/view_model/active_record/has_many_test.rb
420
+ - test/unit/view_model/active_record/has_many_through_poly_test.rb
421
+ - test/unit/view_model/active_record/has_many_through_test.rb
422
+ - test/unit/view_model/active_record/has_one_test.rb
423
+ - test/unit/view_model/active_record/namespacing_test.rb
424
+ - test/unit/view_model/active_record/optional_attribute_view_test.rb
425
+ - test/unit/view_model/active_record/poly_test.rb
426
+ - test/unit/view_model/active_record/shared_test.rb
427
+ - test/unit/view_model/active_record/version_test.rb
428
+ - test/unit/view_model/active_record_test.rb
429
+ - test/unit/view_model/callbacks_test.rb
430
+ - test/unit/view_model/deserialization_error/unique_violation_test.rb
431
+ - test/unit/view_model/record_test.rb
432
+ - test/unit/view_model/traversal_context_test.rb
433
+ - test/unit/view_model_test.rb
434
+ homepage: https://github.com/iknow/cerego_view_models
435
+ licenses:
436
+ - MIT
437
+ metadata: {}
438
+ post_install_message:
439
+ rdoc_options: []
440
+ require_paths:
441
+ - lib
442
+ required_ruby_version: !ruby/object:Gem::Requirement
443
+ requirements:
444
+ - - ">="
445
+ - !ruby/object:Gem::Version
446
+ version: '0'
447
+ required_rubygems_version: !ruby/object:Gem::Requirement
448
+ requirements:
449
+ - - ">="
450
+ - !ruby/object:Gem::Version
451
+ version: '0'
452
+ requirements: []
453
+ rubygems_version: 3.0.3
454
+ signing_key:
455
+ specification_version: 4
456
+ summary: ViewModels provide a means of encapsulating a collection of related data
457
+ and specifying its JSON serialization.
458
+ test_files:
459
+ - test/config/database.yml
460
+ - test/helpers/arvm_test_models.rb
461
+ - test/helpers/arvm_test_utilities.rb
462
+ - test/helpers/callback_tracer.rb
463
+ - test/helpers/controller_test_helpers.rb
464
+ - test/helpers/match_enumerator.rb
465
+ - test/helpers/query_logging.rb
466
+ - test/helpers/test_access_control.rb
467
+ - test/helpers/viewmodel_spec_helpers.rb
468
+ - test/unit/view_model/access_control_test.rb
469
+ - test/unit/view_model/active_record/alias_test.rb
470
+ - test/unit/view_model/active_record/belongs_to_test.rb
471
+ - test/unit/view_model/active_record/cache_test.rb
472
+ - test/unit/view_model/active_record/cloner_test.rb
473
+ - test/unit/view_model/active_record/controller_test.rb
474
+ - test/unit/view_model/active_record/counter_test.rb
475
+ - test/unit/view_model/active_record/customization_test.rb
476
+ - test/unit/view_model/active_record/has_many_test.rb
477
+ - test/unit/view_model/active_record/has_many_through_poly_test.rb
478
+ - test/unit/view_model/active_record/has_many_through_test.rb
479
+ - test/unit/view_model/active_record/has_one_test.rb
480
+ - test/unit/view_model/active_record/namespacing_test.rb
481
+ - test/unit/view_model/active_record/optional_attribute_view_test.rb
482
+ - test/unit/view_model/active_record/poly_test.rb
483
+ - test/unit/view_model/active_record/shared_test.rb
484
+ - test/unit/view_model/active_record/version_test.rb
485
+ - test/unit/view_model/active_record_test.rb
486
+ - test/unit/view_model/callbacks_test.rb
487
+ - test/unit/view_model/deserialization_error/unique_violation_test.rb
488
+ - test/unit/view_model/record_test.rb
489
+ - test/unit/view_model/traversal_context_test.rb
490
+ - test/unit/view_model_test.rb