activerecord_views 0.1.5 → 0.1.6

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/active_record_views/database_tasks.rb +91 -0
  3. data/lib/active_record_views/railtie.rb +0 -4
  4. data/lib/active_record_views/version.rb +1 -1
  5. data/lib/active_record_views.rb +2 -0
  6. metadata +8 -62
  7. data/.gitignore +0 -8
  8. data/.rspec +0 -2
  9. data/.tool-versions +0 -1
  10. data/Appraisals +0 -15
  11. data/Gemfile +0 -3
  12. data/LICENSE.txt +0 -22
  13. data/Rakefile +0 -14
  14. data/activerecord_views.gemspec +0 -27
  15. data/gemfiles/rails5_2.gemfile +0 -7
  16. data/gemfiles/rails6_0.gemfile +0 -7
  17. data/gemfiles/rails6_1.gemfile +0 -7
  18. data/gemfiles/rails7_0.gemfile +0 -7
  19. data/lib/tasks/active_record_views.rake +0 -106
  20. data/spec/active_record_views_checksum_cache_spec.rb +0 -112
  21. data/spec/active_record_views_extension_spec.rb +0 -459
  22. data/spec/active_record_views_spec.rb +0 -344
  23. data/spec/internal/Rakefile +0 -24
  24. data/spec/internal/app/models/dependency_a.rb +0 -3
  25. data/spec/internal/app/models/dependency_b.rb +0 -3
  26. data/spec/internal/app/models/dependency_c.rb +0 -3
  27. data/spec/internal/app/models/erb_test_model.rb +0 -7
  28. data/spec/internal/app/models/erb_test_model.sql.erb +0 -1
  29. data/spec/internal/app/models/external_file_test_model.rb +0 -3
  30. data/spec/internal/app/models/external_file_test_model.sql +0 -1
  31. data/spec/internal/app/models/heredoc_test_model.rb +0 -5
  32. data/spec/internal/app/models/modified_a.rb +0 -3
  33. data/spec/internal/app/models/modified_b.rb +0 -3
  34. data/spec/internal/app/models/namespace/test_model.rb +0 -3
  35. data/spec/internal/app/models/namespace/test_model.sql +0 -1
  36. data/spec/internal/config/database.yml +0 -9
  37. data/spec/internal/config/routes.rb +0 -3
  38. data/spec/spec_helper.rb +0 -130
  39. data/spec/support/silence_warnings.rb +0 -6
  40. data/spec/tasks_spec.rb +0 -113
@@ -1,459 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveRecordViews::Extension do
4
- describe '.is_view' do
5
- def registered_model_class_names
6
- ActiveRecordViews.registered_views.map(&:model_class_name)
7
- end
8
-
9
- def view_exists?(name)
10
- connection = ActiveRecord::Base.connection
11
- connection.view_exists?(name)
12
- end
13
-
14
- it 'creates database views from heredocs' do
15
- expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
16
- expect(HeredocTestModel.first.name).to eq 'Here document'
17
- end
18
-
19
- it 'creates database views from external SQL files' do
20
- expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
21
- expect(ExternalFileTestModel.first.name).to eq 'External SQL file'
22
- end
23
-
24
- it 'creates database views from namespaced external SQL files' do
25
- expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
26
- expect(Namespace::TestModel.first.name).to eq 'Namespaced SQL file'
27
- end
28
-
29
- it 'creates database views from external ERB files' do
30
- expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
31
- expect(ErbTestModel.first.name).to eq 'ERB method file'
32
- end
33
-
34
- it 'errors if external SQL file is missing' do
35
- expect {
36
- class MissingFileTestModel < ActiveRecord::Base
37
- is_view
38
- end
39
- }.to raise_error RuntimeError, /could not find missing_file_test_model.sql/
40
- end
41
-
42
- it 'reloads the database view when external SQL file is modified' do
43
- sql_file = File.join(TEST_TEMP_MODEL_DIR, 'modified_file_test_model.sql')
44
- update_file sql_file, "SELECT 'foo'::text AS test"
45
-
46
- expect {
47
- expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
48
- class ModifiedFileTestModel < ActiveRecord::Base
49
- is_view
50
- end
51
- }.to change { begin; ModifiedFileTestModel.take!.test; rescue NameError; end }.from(nil).to('foo')
52
- .and change { registered_model_class_names.include?('ModifiedFileTestModel') }.from(false).to(true)
53
-
54
- expect {
55
- update_file sql_file, "SELECT 'bar'::text AS test, 42::integer AS test2"
56
- }.to_not change { ModifiedFileTestModel.take!.test }
57
-
58
- expect {
59
- expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
60
- test_request
61
- test_request # second request does not `create_view` again
62
- }.to change { ModifiedFileTestModel.take!.test }.to('bar')
63
- .and change { ModifiedFileTestModel.column_names }.from(%w[test]).to(%w[test test2])
64
-
65
- expect {
66
- update_file sql_file, "SELECT 'baz'::text AS test"
67
- }.to_not change { ModifiedFileTestModel.take!.test }
68
-
69
- expect {
70
- expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
71
- test_request
72
- }.to change { ModifiedFileTestModel.take!.test }.to('baz')
73
-
74
- File.unlink sql_file
75
- test_request # trigger cleanup
76
- end
77
-
78
- it 'reloads the database view when external ERB SQL file is modified' do
79
- ['foo 42', 'bar 42'].each do |sql|
80
- expect(ActiveRecordViews).to receive(:create_view).with(
81
- anything,
82
- 'modified_erb_file_test_models',
83
- 'ModifiedErbFileTestModel',
84
- sql,
85
- {}
86
- ).once.ordered
87
- end
88
-
89
- sql_file = File.join(TEST_TEMP_MODEL_DIR, 'modified_erb_file_test_model.sql.erb')
90
- update_file sql_file, 'foo <%= test_erb_method %>'
91
-
92
- class ModifiedErbFileTestModel < ActiveRecord::Base
93
- def self.test_erb_method
94
- 2 * 3 * 7
95
- end
96
-
97
- is_view
98
- end
99
-
100
- update_file sql_file, 'bar <%= test_erb_method %>'
101
- test_request
102
-
103
- File.unlink sql_file
104
- test_request # trigger cleanup
105
- end
106
-
107
- it 'drops the view if the external SQL file is deleted' do
108
- sql_file = File.join(TEST_TEMP_MODEL_DIR, 'deleted_file_test_model.sql')
109
- File.write sql_file, "SELECT 1 AS id, 'delete test'::text AS name"
110
-
111
- rb_file = 'spec/internal/app/models_temp/deleted_file_test_model.rb'
112
- File.write rb_file, <<~RB
113
- class DeletedFileTestModel < ActiveRecord::Base
114
- is_view
115
- end
116
- RB
117
-
118
- Rails.application.reloader.wrap do
119
- expect(DeletedFileTestModel.first.name).to eq 'delete test'
120
- end
121
-
122
- File.unlink sql_file
123
- File.unlink rb_file
124
-
125
- expect(ActiveRecord::Base.connection).to receive(:execute).with(/\ADROP/).once.and_call_original
126
- expect {
127
- test_request
128
- }.to change { registered_model_class_names.include?('DeletedFileTestModel') }.from(true).to(false)
129
- .and change { view_exists?('deleted_file_test_models') }.from(true).to(false)
130
- test_request # second request does not `drop_view` again
131
-
132
- expect {
133
- DeletedFileTestModel.first.name
134
- }.to raise_error NameError, 'uninitialized constant DeletedFileTestModel'
135
- end
136
-
137
- it 'does not create if database view is initially up to date' do
138
- ActiveRecordViews.create_view ActiveRecord::Base.connection, 'initial_create_test_models', 'InitialCreateTestModel', 'SELECT 42 as id'
139
- expect(ActiveRecord::Base.connection).to receive(:execute).with(/\ACREATE (?:OR REPLACE )?VIEW/).never
140
- class InitialCreateTestModel < ActiveRecord::Base
141
- is_view 'SELECT 42 as id'
142
- end
143
- end
144
-
145
- it 'successfully recreates modified paired views with incompatible changes' do
146
- without_dependency_checks do
147
- ActiveRecordViews.create_view ActiveRecord::Base.connection, 'modified_as', 'ModifiedA', 'SELECT 11 AS old_name;'
148
- ActiveRecordViews.create_view ActiveRecord::Base.connection, 'modified_bs', 'ModifiedB', 'SELECT old_name FROM modified_as;'
149
- end
150
-
151
- expect(ModifiedB.first.attributes.except(nil)).to eq('new_name' => 22)
152
- end
153
-
154
- it 'successfully restores dependant view when temporarily dropping dependency' do
155
- without_dependency_checks do
156
- ActiveRecordViews.create_view ActiveRecord::Base.connection, 'dependency_as', 'DependencyA', 'SELECT 42 AS foo, 1 AS id;'
157
- ActiveRecordViews.create_view ActiveRecord::Base.connection, 'dependency_bs', 'DependencyB', 'SELECT id FROM dependency_as;'
158
- end
159
-
160
- expect(DependencyA.first.id).to eq 2
161
- expect(DependencyB.first.id).to eq 2
162
- end
163
-
164
- it 'sucessfully restore dependant view and dependency when loading from middle outwards' do
165
- without_dependency_checks do
166
- ActiveRecordViews.create_view ActiveRecord::Base.connection, 'dependency_as', 'DependencyA', 'SELECT 42 AS foo, 1 AS id;'
167
- ActiveRecordViews.create_view ActiveRecord::Base.connection, 'dependency_bs', 'DependencyB', 'SELECT id FROM dependency_as;'
168
- ActiveRecordViews.create_view ActiveRecord::Base.connection, 'dependency_cs', 'DependencyC', 'SELECT id FROM dependency_bs;'
169
- end
170
-
171
- expect(DependencyB.first.id).to eq 2
172
- end
173
-
174
- it 'errors if more than one argument is specified' do
175
- expect {
176
- class TooManyArguments < ActiveRecord::Base
177
- is_view 'SELECT 1 AS ID;', 'SELECT 2 AS ID;'
178
- end
179
- }.to raise_error ArgumentError, 'wrong number of arguments (2 for 0..1)'
180
- end
181
-
182
- it 'errors if an invalid option is specified' do
183
- expect {
184
- class InvalidOption < ActiveRecord::Base
185
- is_view 'SELECT 1 AS ID;', blargh: 123
186
- end
187
- }.to raise_error ArgumentError, /^Unknown key: :?blargh/
188
- end
189
-
190
- it 'creates/refreshes/drops materialized views' do
191
- sql_file = File.join(TEST_TEMP_MODEL_DIR, 'materialized_view_test_model.sql')
192
- File.write sql_file, 'SELECT 123 AS id;'
193
-
194
- class MaterializedViewTestModel < ActiveRecord::Base
195
- is_view materialized: true
196
- end
197
-
198
- expect {
199
- MaterializedViewTestModel.first!
200
- }.to raise_error ActiveRecord::StatementInvalid, /materialized view "materialized_view_test_models" has not been populated/
201
-
202
- expect(MaterializedViewTestModel.view_populated?).to eq false
203
- expect(MaterializedViewTestModel.refreshed_at).to eq nil
204
-
205
- MaterializedViewTestModel.refresh_view!
206
-
207
- expect(MaterializedViewTestModel.view_populated?).to eq true
208
- expect(MaterializedViewTestModel.refreshed_at).to be_a Time
209
- expect(MaterializedViewTestModel.refreshed_at.zone).to eq 'UTC'
210
- expect(MaterializedViewTestModel.refreshed_at).to be_within(1.second).of Time.now
211
-
212
- expect(MaterializedViewTestModel.first!.id).to eq 123
213
-
214
- File.unlink sql_file
215
-
216
- expect {
217
- test_request
218
- }.to change { view_exists?('materialized_view_test_models') }.from(true).to(false)
219
- end
220
-
221
- it 'raises an error for `view_populated?` if view is not materialized' do
222
- class NonMaterializedViewPopulatedTestModel < ActiveRecord::Base
223
- is_view 'SELECT 1 AS id;'
224
- end
225
-
226
- expect {
227
- NonMaterializedViewPopulatedTestModel.view_populated?
228
- }.to raise_error ArgumentError, 'not a materialized view'
229
- end
230
-
231
- it 'supports ensuring a view hierarchy has been populated' do
232
- class EnsurePopulatedFoo < ActiveRecord::Base
233
- is_view 'SELECT 1 AS id;', materialized: true
234
- end
235
-
236
- class EnsurePopulatedBar < ActiveRecord::Base
237
- is_view "SELECT * FROM #{EnsurePopulatedFoo.table_name}", dependencies: [EnsurePopulatedFoo]
238
- end
239
-
240
- class EnsurePopulatedBaz < ActiveRecord::Base
241
- is_view "SELECT * FROM #{EnsurePopulatedBar.table_name}", dependencies: [EnsurePopulatedBar]
242
- end
243
-
244
- expect(ActiveRecord::Base.connection).to receive(:execute).with('REFRESH MATERIALIZED VIEW "ensure_populated_foos";').once.and_call_original
245
- allow(ActiveRecord::Base.connection).to receive(:execute).and_call_original
246
-
247
- expect(EnsurePopulatedFoo.view_populated?).to eq false
248
- EnsurePopulatedBaz.ensure_populated!
249
- expect(EnsurePopulatedFoo.view_populated?).to eq true
250
- EnsurePopulatedBaz.ensure_populated!
251
- expect(EnsurePopulatedFoo.view_populated?).to eq true
252
- end
253
-
254
- it 'invalidates ActiveRecord query cache after populating' do
255
- class EnsurePopulatedCache < ActiveRecord::Base
256
- is_view 'SELECT 1 AS id;', materialized: true
257
- end
258
-
259
- expect(ActiveRecord::Base.connection).to receive(:execute).with('REFRESH MATERIALIZED VIEW "ensure_populated_caches";').once.and_call_original
260
- allow(ActiveRecord::Base.connection).to receive(:execute).and_call_original
261
-
262
- ActiveRecord::Base.connection.cache do
263
- expect(EnsurePopulatedCache.view_populated?).to eq false
264
- EnsurePopulatedCache.ensure_populated!
265
- expect(EnsurePopulatedCache.view_populated?).to eq true
266
- EnsurePopulatedCache.ensure_populated!
267
- expect(EnsurePopulatedCache.view_populated?).to eq true
268
- end
269
- end
270
-
271
- it 'supports refreshing materialized views concurrently' do
272
- class MaterializedViewRefreshTestModel < ActiveRecord::Base
273
- is_view 'SELECT 1 AS id;', materialized: true
274
- end
275
- class MaterializedViewConcurrentRefreshTestModel < ActiveRecord::Base
276
- is_view 'SELECT 1 AS id;', materialized: true, unique_columns: [:id]
277
- end
278
- MaterializedViewRefreshTestModel.refresh_view!
279
- MaterializedViewConcurrentRefreshTestModel.refresh_view!
280
-
281
- sql_statements.clear
282
-
283
- MaterializedViewRefreshTestModel.refresh_view!
284
- MaterializedViewRefreshTestModel.refresh_view! concurrent: false
285
- expect {
286
- MaterializedViewRefreshTestModel.refresh_view! concurrent: true
287
- }.to raise_error ActiveRecord::StatementInvalid, /^PG::ObjectNotInPrerequisiteState: ERROR: +cannot refresh/
288
- MaterializedViewConcurrentRefreshTestModel.refresh_view!
289
- MaterializedViewConcurrentRefreshTestModel.refresh_view! concurrent: false
290
- MaterializedViewConcurrentRefreshTestModel.refresh_view! concurrent: true
291
-
292
- expect(sql_statements.grep_v(/^SELECT/)).to eq [
293
- 'BEGIN',
294
- 'REFRESH MATERIALIZED VIEW "materialized_view_refresh_test_models";',
295
- "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_refresh_test_models';",
296
- 'COMMIT',
297
-
298
- 'BEGIN',
299
- 'REFRESH MATERIALIZED VIEW "materialized_view_refresh_test_models";',
300
- "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_refresh_test_models';",
301
- 'COMMIT',
302
-
303
- 'BEGIN',
304
- 'REFRESH MATERIALIZED VIEW CONCURRENTLY "materialized_view_refresh_test_models";',
305
- 'ROLLBACK',
306
-
307
- 'BEGIN',
308
- 'REFRESH MATERIALIZED VIEW CONCURRENTLY "materialized_view_concurrent_refresh_test_models";',
309
- "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_concurrent_refresh_test_models';",
310
- 'COMMIT',
311
-
312
- 'BEGIN',
313
- 'REFRESH MATERIALIZED VIEW "materialized_view_concurrent_refresh_test_models";',
314
- "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_concurrent_refresh_test_models';",
315
- 'COMMIT',
316
-
317
- 'BEGIN',
318
- 'REFRESH MATERIALIZED VIEW CONCURRENTLY "materialized_view_concurrent_refresh_test_models";',
319
- "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_concurrent_refresh_test_models';",
320
- 'COMMIT',
321
- ]
322
- end
323
-
324
- it 'supports opportunistically refreshing materialized views concurrently' do
325
- class MaterializedViewAutoRefreshTestModel < ActiveRecord::Base
326
- is_view 'SELECT 1 AS id;', materialized: true, unique_columns: [:id]
327
- end
328
-
329
- sql_statements.clear
330
-
331
- MaterializedViewAutoRefreshTestModel.refresh_view! concurrent: :auto
332
- MaterializedViewAutoRefreshTestModel.refresh_view! concurrent: :auto
333
- MaterializedViewAutoRefreshTestModel.refresh_view! concurrent: :auto
334
-
335
- expect(sql_statements.grep_v(/^SELECT/)).to eq [
336
- 'BEGIN',
337
- 'REFRESH MATERIALIZED VIEW "materialized_view_auto_refresh_test_models";',
338
- "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_auto_refresh_test_models';",
339
- 'COMMIT',
340
-
341
- 'BEGIN',
342
- 'REFRESH MATERIALIZED VIEW CONCURRENTLY "materialized_view_auto_refresh_test_models";',
343
- "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_auto_refresh_test_models';",
344
- 'COMMIT',
345
-
346
- 'BEGIN',
347
- 'REFRESH MATERIALIZED VIEW CONCURRENTLY "materialized_view_auto_refresh_test_models";',
348
- "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_auto_refresh_test_models';",
349
- 'COMMIT',
350
- ]
351
- end
352
-
353
- it 'raises an error when refreshing materialized views with invalid concurrent option' do
354
- class MaterializedViewInvalidRefreshTestModel < ActiveRecord::Base
355
- is_view 'SELECT 1 AS id;', materialized: true, unique_columns: [:id]
356
- end
357
-
358
- expect {
359
- MaterializedViewAutoRefreshTestModel.refresh_view! concurrent: :blah
360
- }.to raise_error ArgumentError, 'invalid concurrent option'
361
- end
362
-
363
- it 'errors if dependencies are not specified' do
364
- class DependencyCheckBase1 < ActiveRecord::Base
365
- self.table_name = 'dependency_check_base1'
366
- is_view 'SELECT 1 AS ID;'
367
- end
368
- class DependencyCheckBase2 < ActiveRecord::Base
369
- self.table_name = 'dependency_check_base2'
370
- is_view 'SELECT 1 AS ID;'
371
- end
372
- ActiveRecord::Base.connection.execute 'CREATE VIEW dependency_check_base_unmanaged AS SELECT 1 AS ID;'
373
-
374
- expect {
375
- class DependencyCheckGood < ActiveRecord::Base
376
- is_view 'SELECT * FROM dependency_check_base1;', dependencies: [DependencyCheckBase1]
377
- end
378
- }.to_not raise_error
379
-
380
- expect {
381
- class DependencyCheckGoodUnmanaged < ActiveRecord::Base
382
- is_view 'SELECT * FROM dependency_check_base_unmanaged;'
383
- end
384
- }.to_not raise_error
385
-
386
- expect {
387
- class DependencyCheckMissing1 < ActiveRecord::Base
388
- is_view 'SELECT * FROM dependency_check_base1 UNION ALL SELECT * FROM dependency_check_base2;', dependencies: [DependencyCheckBase1]
389
- end
390
- }.to raise_error ArgumentError, 'DependencyCheckBase2 must be specified as a dependency of DependencyCheckMissing1: `is_view dependencies: [DependencyCheckBase1, DependencyCheckBase2]`'
391
-
392
- expect {
393
- class DependencyCheckMissing2 < ActiveRecord::Base
394
- is_view 'SELECT * FROM dependency_check_base1 UNION ALL SELECT * FROM dependency_check_base2;', dependencies: []
395
- end
396
- }.to raise_error ArgumentError, 'DependencyCheckBase1 and DependencyCheckBase2 must be specified as dependencies of DependencyCheckMissing2: `is_view dependencies: [DependencyCheckBase1, DependencyCheckBase2]`'
397
-
398
- expect {
399
- class DependencyCheckNested < ActiveRecord::Base
400
- is_view 'SELECT 1 FROM dependency_check_goods'
401
- end
402
- }.to raise_error ArgumentError, 'DependencyCheckGood must be specified as a dependency of DependencyCheckNested: `is_view dependencies: [DependencyCheckGood]`'
403
-
404
- expect {
405
- class DependencyCheckExtra1 < ActiveRecord::Base
406
- is_view 'SELECT * FROM dependency_check_base1;', dependencies: [DependencyCheckBase1, DependencyCheckBase2]
407
- end
408
- }.to raise_error ArgumentError, 'DependencyCheckBase2 is not a dependency of DependencyCheckExtra1'
409
-
410
- expect {
411
- class DependencyCheckExtra2 < ActiveRecord::Base
412
- is_view 'SELECT 1 AS id;', dependencies: [DependencyCheckBase1, DependencyCheckBase2]
413
- end
414
- }.to raise_error ArgumentError, 'DependencyCheckBase1 and DependencyCheckBase2 are not dependencies of DependencyCheckExtra2'
415
-
416
- expect {
417
- class DependencyCheckWrongType < ActiveRecord::Base
418
- is_view 'SELECT 1;', dependencies: %w[DependencyCheckBase1]
419
- end
420
- }.to raise_error ArgumentError, 'dependencies must be ActiveRecord classes'
421
-
422
- expect(view_names).to match_array %w[
423
- dependency_check_base1
424
- dependency_check_base2
425
- dependency_check_base_unmanaged
426
-
427
- dependency_check_goods
428
- dependency_check_good_unmanageds
429
- ]
430
- end
431
-
432
- context 'without create_enabled' do
433
- around do |example|
434
- without_create_enabled(&example)
435
- end
436
-
437
- it 'delays create_view until process_create_queue! is called' do
438
- allow(ActiveRecordViews).to receive(:create_view).and_call_original
439
-
440
- expect(ActiveRecordViews::Extension.create_queue.size).to eq 0
441
- expect(ActiveRecordViews).to_not have_received(:create_view)
442
-
443
- expect {
444
- expect(HeredocTestModel.first.name).to eq 'Here document'
445
- }.to raise_error ActiveRecord::StatementInvalid
446
-
447
- expect(ActiveRecordViews::Extension.create_queue.size).to eq 1
448
- expect(ActiveRecordViews).to_not have_received(:create_view)
449
-
450
- ActiveRecordViews::Extension.process_create_queue!
451
-
452
- expect(ActiveRecordViews::Extension.create_queue.size).to eq 0
453
- expect(ActiveRecordViews).to have_received(:create_view)
454
-
455
- expect(HeredocTestModel.first.name).to eq 'Here document'
456
- end
457
- end
458
- end
459
- end