activerecord_views 0.0.19 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,19 @@ require 'spec_helper'
2
2
 
3
3
  describe ActiveRecordViews::Extension do
4
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
+ if connection.respond_to?(:view_exists?)
12
+ connection.view_exists?(name)
13
+ else
14
+ connection.table_exists?(name)
15
+ end
16
+ end
17
+
5
18
  it 'creates database views from heredocs' do
6
19
  expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
7
20
  expect(HeredocTestModel.first.name).to eq 'Here document'
@@ -19,43 +32,50 @@ describe ActiveRecordViews::Extension do
19
32
 
20
33
  it 'creates database views from external ERB files' do
21
34
  expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
22
- expect(ErbTestModel.first.name).to eq 'ERB file'
35
+ expect(ErbTestModel.first.name).to eq 'ERB method file'
23
36
  end
24
37
 
25
38
  it 'errors if external SQL file is missing' do
26
39
  expect {
27
- MissingFileTestModel
40
+ class MissingFileTestModel < ActiveRecord::Base
41
+ is_view
42
+ end
28
43
  }.to raise_error RuntimeError, /could not find missing_file_test_model.sql/
29
44
  end
30
45
 
31
46
  it 'reloads the database view when external SQL file is modified' do
32
- %w[foo bar baz].each do |sql|
33
- expect(ActiveRecordViews).to receive(:create_view).with(
34
- anything,
35
- 'modified_file_test_models',
36
- 'ModifiedFileTestModel',
37
- sql,
38
- {}
39
- ).once.ordered
40
- end
41
-
42
- with_temp_sql_dir do |temp_dir|
43
- sql_file = File.join(temp_dir, 'modified_file_test_model.sql')
44
- update_file sql_file, 'foo'
47
+ sql_file = File.join(TEST_TEMP_MODEL_DIR, 'modified_file_test_model.sql')
48
+ update_file sql_file, "SELECT 'foo'::text AS test"
45
49
 
50
+ expect {
51
+ expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
46
52
  class ModifiedFileTestModel < ActiveRecord::Base
47
53
  is_view
48
54
  end
55
+ }.to change { begin; ModifiedFileTestModel.take!.test; rescue NameError; end }.from(nil).to('foo')
56
+ .and change { registered_model_class_names.include?('ModifiedFileTestModel') }.from(false).to(true)
49
57
 
50
- update_file sql_file, 'bar'
58
+ expect {
59
+ update_file sql_file, "SELECT 'bar'::text AS test, 42::integer AS test2"
60
+ }.to_not change { ModifiedFileTestModel.take!.test }
51
61
 
62
+ expect {
63
+ expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
52
64
  test_request
53
65
  test_request # second request does not `create_view` again
66
+ }.to change { ModifiedFileTestModel.take!.test }.to('bar')
67
+ .and change { ModifiedFileTestModel.column_names }.from(%w[test]).to(%w[test test2])
54
68
 
55
- update_file sql_file, 'baz'
69
+ expect {
70
+ update_file sql_file, "SELECT 'baz'::text AS test"
71
+ }.to_not change { ModifiedFileTestModel.take!.test }
56
72
 
73
+ expect {
74
+ expect(ActiveRecordViews).to receive(:create_view).once.and_call_original
57
75
  test_request
58
- end
76
+ }.to change { ModifiedFileTestModel.take!.test }.to('baz')
77
+
78
+ File.unlink sql_file
59
79
  test_request # trigger cleanup
60
80
  end
61
81
 
@@ -70,40 +90,53 @@ describe ActiveRecordViews::Extension do
70
90
  ).once.ordered
71
91
  end
72
92
 
73
- with_temp_sql_dir do |temp_dir|
74
- sql_file = File.join(temp_dir, 'modified_erb_file_test_model.sql.erb')
75
- update_file sql_file, 'foo <%= 2*3*7 %>'
93
+ sql_file = File.join(TEST_TEMP_MODEL_DIR, 'modified_erb_file_test_model.sql.erb')
94
+ update_file sql_file, 'foo <%= test_erb_method %>'
76
95
 
77
- class ModifiedErbFileTestModel < ActiveRecord::Base
78
- is_view
96
+ class ModifiedErbFileTestModel < ActiveRecord::Base
97
+ def self.test_erb_method
98
+ 2 * 3 * 7
79
99
  end
80
100
 
81
- update_file sql_file, 'bar <%= 2*3*7 %>'
82
- test_request
101
+ is_view
83
102
  end
103
+
104
+ update_file sql_file, 'bar <%= test_erb_method %>'
105
+ test_request
106
+
107
+ File.unlink sql_file
84
108
  test_request # trigger cleanup
85
109
  end
86
110
 
87
111
  it 'drops the view if the external SQL file is deleted' do
88
- with_temp_sql_dir do |temp_dir|
89
- sql_file = File.join(temp_dir, 'deleted_file_test_model.sql')
90
- File.write sql_file, "SELECT 1 AS id, 'delete test'::text AS name"
112
+ sql_file = File.join(TEST_TEMP_MODEL_DIR, 'deleted_file_test_model.sql')
113
+ File.write sql_file, "SELECT 1 AS id, 'delete test'::text AS name"
91
114
 
115
+ rb_file = 'spec/internal/app/models_temp/deleted_file_test_model.rb'
116
+ File.write rb_file, <<~RB
92
117
  class DeletedFileTestModel < ActiveRecord::Base
93
118
  is_view
94
119
  end
120
+ RB
95
121
 
122
+ with_reloader do
96
123
  expect(DeletedFileTestModel.first.name).to eq 'delete test'
124
+ end
97
125
 
98
- File.unlink sql_file
126
+ File.unlink sql_file
127
+ File.unlink rb_file
99
128
 
100
- expect(ActiveRecord::Base.connection).to receive(:execute).with(/\ADROP/).once.and_call_original
129
+ expect(ActiveRecord::Base.connection).to receive(:execute).with(/\ADROP/).once.and_call_original
130
+ expect {
101
131
  test_request
102
- test_request # second request does not `drop_view` again
132
+ }.to change { registered_model_class_names.include?('DeletedFileTestModel') }.from(true).to(false)
133
+ .and change { view_exists?('deleted_file_test_models') }.from(true).to(false)
134
+ test_request # second request does not `drop_view` again
103
135
 
136
+ if Rails::VERSION::MAJOR >= 5
104
137
  expect {
105
138
  DeletedFileTestModel.first.name
106
- }.to raise_error ActiveRecord::StatementInvalid, /relation "deleted_file_test_models" does not exist/
139
+ }.to raise_error NameError, 'uninitialized constant DeletedFileTestModel'
107
140
  end
108
141
  end
109
142
 
@@ -161,37 +194,34 @@ describe ActiveRecordViews::Extension do
161
194
  end
162
195
 
163
196
  it 'creates/refreshes/drops materialized views' do
164
- with_temp_sql_dir do |temp_dir|
165
- sql_file = File.join(temp_dir, 'materialized_view_test_model.sql')
166
- File.write sql_file, 'SELECT 123 AS id;'
197
+ sql_file = File.join(TEST_TEMP_MODEL_DIR, 'materialized_view_test_model.sql')
198
+ File.write sql_file, 'SELECT 123 AS id;'
167
199
 
168
- class MaterializedViewTestModel < ActiveRecord::Base
169
- is_view materialized: true
170
- end
200
+ class MaterializedViewTestModel < ActiveRecord::Base
201
+ is_view materialized: true
202
+ end
171
203
 
172
- expect {
173
- MaterializedViewTestModel.first!
174
- }.to raise_error ActiveRecord::StatementInvalid, /materialized view "materialized_view_test_models" has not been populated/
204
+ expect {
205
+ MaterializedViewTestModel.first!
206
+ }.to raise_error ActiveRecord::StatementInvalid, /materialized view "materialized_view_test_models" has not been populated/
175
207
 
176
- expect(MaterializedViewTestModel.view_populated?).to eq false
177
- expect(MaterializedViewTestModel.refreshed_at).to eq nil
208
+ expect(MaterializedViewTestModel.view_populated?).to eq false
209
+ expect(MaterializedViewTestModel.refreshed_at).to eq nil
178
210
 
179
- MaterializedViewTestModel.refresh_view!
211
+ MaterializedViewTestModel.refresh_view!
180
212
 
181
- expect(MaterializedViewTestModel.view_populated?).to eq true
182
- expect(MaterializedViewTestModel.refreshed_at).to be_a ActiveSupport::TimeWithZone
183
- expect(MaterializedViewTestModel.refreshed_at.zone).to eq 'UTC'
184
- expect(MaterializedViewTestModel.refreshed_at).to be_within(1.second).of Time.now
213
+ expect(MaterializedViewTestModel.view_populated?).to eq true
214
+ expect(MaterializedViewTestModel.refreshed_at).to be_a Time
215
+ expect(MaterializedViewTestModel.refreshed_at.zone).to eq 'UTC'
216
+ expect(MaterializedViewTestModel.refreshed_at).to be_within(1.second).of Time.now
185
217
 
186
- expect(MaterializedViewTestModel.first!.id).to eq 123
218
+ expect(MaterializedViewTestModel.first!.id).to eq 123
187
219
 
188
- File.unlink sql_file
189
- test_request
220
+ File.unlink sql_file
190
221
 
191
- expect {
192
- MaterializedViewTestModel.first!
193
- }.to raise_error ActiveRecord::StatementInvalid, /relation "materialized_view_test_models" does not exist/
194
- end
222
+ expect {
223
+ test_request
224
+ }.to change { view_exists?('materialized_view_test_models') }.from(true).to(false)
195
225
  end
196
226
 
197
227
  it 'raises an error for `view_populated?` if view is not materialized' do
@@ -217,7 +247,7 @@ describe ActiveRecordViews::Extension do
217
247
  is_view "SELECT * FROM #{EnsurePopulatedBar.table_name}", dependencies: [EnsurePopulatedBar]
218
248
  end
219
249
 
220
- expect(ActiveRecord::Base.connection).to receive(:execute).with(/^REFRESH MATERIALIZED VIEW/).once.and_call_original
250
+ expect(ActiveRecord::Base.connection).to receive(:execute).with('REFRESH MATERIALIZED VIEW "ensure_populated_foos";').once.and_call_original
221
251
  allow(ActiveRecord::Base.connection).to receive(:execute).and_call_original
222
252
 
223
253
  expect(EnsurePopulatedFoo.view_populated?).to eq false
@@ -227,6 +257,23 @@ describe ActiveRecordViews::Extension do
227
257
  expect(EnsurePopulatedFoo.view_populated?).to eq true
228
258
  end
229
259
 
260
+ it 'invalidates ActiveRecord query cache after populating' do
261
+ class EnsurePopulatedCache < ActiveRecord::Base
262
+ is_view 'SELECT 1 AS id;', materialized: true
263
+ end
264
+
265
+ expect(ActiveRecord::Base.connection).to receive(:execute).with('REFRESH MATERIALIZED VIEW "ensure_populated_caches";').once.and_call_original
266
+ allow(ActiveRecord::Base.connection).to receive(:execute).and_call_original
267
+
268
+ ActiveRecord::Base.connection.cache do
269
+ expect(EnsurePopulatedCache.view_populated?).to eq false
270
+ EnsurePopulatedCache.ensure_populated!
271
+ expect(EnsurePopulatedCache.view_populated?).to eq true
272
+ EnsurePopulatedCache.ensure_populated!
273
+ expect(EnsurePopulatedCache.view_populated?).to eq true
274
+ end
275
+ end
276
+
230
277
  it 'supports refreshing materialized views concurrently' do
231
278
  class MaterializedViewRefreshTestModel < ActiveRecord::Base
232
279
  is_view 'SELECT 1 AS id;', materialized: true
@@ -234,23 +281,50 @@ describe ActiveRecordViews::Extension do
234
281
  class MaterializedViewConcurrentRefreshTestModel < ActiveRecord::Base
235
282
  is_view 'SELECT 1 AS id;', materialized: true, unique_columns: [:id]
236
283
  end
284
+ MaterializedViewRefreshTestModel.refresh_view!
237
285
  MaterializedViewConcurrentRefreshTestModel.refresh_view!
238
286
 
239
- [
287
+ sql_statements.clear
288
+
289
+ MaterializedViewRefreshTestModel.refresh_view!
290
+ MaterializedViewRefreshTestModel.refresh_view! concurrent: false
291
+ expect {
292
+ MaterializedViewRefreshTestModel.refresh_view! concurrent: true
293
+ }.to raise_error ActiveRecord::StatementInvalid, /^PG::ObjectNotInPrerequisiteState: ERROR: +cannot refresh/
294
+ MaterializedViewConcurrentRefreshTestModel.refresh_view!
295
+ MaterializedViewConcurrentRefreshTestModel.refresh_view! concurrent: false
296
+ MaterializedViewConcurrentRefreshTestModel.refresh_view! concurrent: true
297
+
298
+ expect(sql_statements.grep_v(/^SELECT/)).to eq [
240
299
  'BEGIN',
241
300
  'REFRESH MATERIALIZED VIEW "materialized_view_refresh_test_models";',
242
301
  "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_refresh_test_models';",
243
302
  'COMMIT',
303
+
304
+ 'BEGIN',
305
+ 'REFRESH MATERIALIZED VIEW "materialized_view_refresh_test_models";',
306
+ "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_refresh_test_models';",
307
+ 'COMMIT',
308
+
309
+ 'BEGIN',
310
+ 'REFRESH MATERIALIZED VIEW CONCURRENTLY "materialized_view_refresh_test_models";',
311
+ 'ROLLBACK',
312
+
244
313
  'BEGIN',
245
314
  'REFRESH MATERIALIZED VIEW CONCURRENTLY "materialized_view_concurrent_refresh_test_models";',
246
315
  "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_concurrent_refresh_test_models';",
247
316
  'COMMIT',
248
- ].each do |sql|
249
- expect(ActiveRecord::Base.connection).to receive(:execute).with(sql).once.and_call_original
250
- end
251
317
 
252
- MaterializedViewRefreshTestModel.refresh_view!
253
- MaterializedViewConcurrentRefreshTestModel.refresh_view! concurrent: true
318
+ 'BEGIN',
319
+ 'REFRESH MATERIALIZED VIEW "materialized_view_concurrent_refresh_test_models";',
320
+ "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_concurrent_refresh_test_models';",
321
+ 'COMMIT',
322
+
323
+ 'BEGIN',
324
+ 'REFRESH MATERIALIZED VIEW CONCURRENTLY "materialized_view_concurrent_refresh_test_models";',
325
+ "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_concurrent_refresh_test_models';",
326
+ 'COMMIT',
327
+ ]
254
328
  end
255
329
 
256
330
  it 'supports opportunistically refreshing materialized views concurrently' do
@@ -258,21 +332,28 @@ describe ActiveRecordViews::Extension do
258
332
  is_view 'SELECT 1 AS id;', materialized: true, unique_columns: [:id]
259
333
  end
260
334
 
261
- [
335
+ sql_statements.clear
336
+
337
+ MaterializedViewAutoRefreshTestModel.refresh_view! concurrent: :auto
338
+ MaterializedViewAutoRefreshTestModel.refresh_view! concurrent: :auto
339
+ MaterializedViewAutoRefreshTestModel.refresh_view! concurrent: :auto
340
+
341
+ expect(sql_statements.grep_v(/^SELECT/)).to eq [
262
342
  'BEGIN',
263
343
  'REFRESH MATERIALIZED VIEW "materialized_view_auto_refresh_test_models";',
264
344
  "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_auto_refresh_test_models';",
265
345
  'COMMIT',
346
+
266
347
  'BEGIN',
267
348
  'REFRESH MATERIALIZED VIEW CONCURRENTLY "materialized_view_auto_refresh_test_models";',
268
349
  "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_auto_refresh_test_models';",
269
350
  'COMMIT',
270
- ].each do |sql|
271
- expect(ActiveRecord::Base.connection).to receive(:execute).with(sql).once.and_call_original
272
- end
273
351
 
274
- MaterializedViewAutoRefreshTestModel.refresh_view! concurrent: :auto
275
- MaterializedViewAutoRefreshTestModel.refresh_view! concurrent: :auto
352
+ 'BEGIN',
353
+ 'REFRESH MATERIALIZED VIEW CONCURRENTLY "materialized_view_auto_refresh_test_models";',
354
+ "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'materialized_view_auto_refresh_test_models';",
355
+ 'COMMIT',
356
+ ]
276
357
  end
277
358
 
278
359
  it 'raises an error when refreshing materialized views with invalid concurrent option' do
@@ -20,6 +20,28 @@ describe ActiveRecordViews do
20
20
  SQL
21
21
  end
22
22
 
23
+ def test_view_populated?
24
+ value = connection.select_value(<<~SQL)
25
+ SELECT ispopulated
26
+ FROM pg_matviews
27
+ WHERE schemaname = 'public' AND matviewname = 'test'
28
+ SQL
29
+
30
+ if Rails::VERSION::MAJOR < 5
31
+ value = ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(value)
32
+ end
33
+
34
+ value
35
+ end
36
+
37
+ def test_view_refreshed_at
38
+ connection.select_value(<<~SQL)
39
+ SELECT refreshed_at
40
+ FROM active_record_views
41
+ WHERE name = 'test'
42
+ SQL
43
+ end
44
+
23
45
  def test_materialized_view_sql
24
46
  connection.select_value(<<-SQL.squish).try(&:squish)
25
47
  SELECT definition
@@ -120,6 +142,21 @@ describe ActiveRecordViews do
120
142
  expect(view_names).to match_array %w[unmanaged]
121
143
  end
122
144
 
145
+ it 'support being ran inside a transaction' do
146
+ expect(ActiveRecordViews).to receive(:without_transaction).at_least(:once).and_wrap_original do |original, *args, &block|
147
+ original.call(*args) do |new_connection|
148
+ new_connection.execute 'SET statement_timeout = 1000'
149
+ block.call(new_connection)
150
+ end
151
+ end
152
+
153
+ connection.transaction requires_new: true do
154
+ expect {
155
+ ActiveRecordViews.drop_all_views connection
156
+ }.to change { view_names }
157
+ end
158
+ end
159
+
123
160
  it 'errors if an unmanaged view depends on a managed view' do
124
161
  connection.execute 'CREATE VIEW unmanaged AS SELECT * from dependant2a'
125
162
 
@@ -213,6 +250,28 @@ describe ActiveRecordViews do
213
250
  create_test_view 'select 1 as foo, 2 as bar, 3 as baz', materialized: false, unique_columns: [:foo, 'bar']
214
251
  }.to raise_error ArgumentError, 'unique_columns option requires view to be materialized'
215
252
  end
253
+
254
+ it 'supports resetting all materialised views' do
255
+ class ResetMaterializeViewTestModel < ActiveRecord::Base
256
+ self.table_name = 'test'
257
+ is_view 'select 123 as id', materialized: true
258
+ end
259
+ ResetMaterializeViewTestModel.refresh_view!
260
+
261
+ expect {
262
+ ActiveRecordViews.reset_materialized_views
263
+ }.to change { test_view_populated? }.to(false)
264
+ .and change { test_view_refreshed_at }.to(nil)
265
+ end
266
+ end
267
+
268
+ describe '.drop_all_views' do
269
+ let(:connection) { ActiveRecord::Base.connection }
270
+
271
+ it 'does nothing when no views have been defined' do
272
+ ActiveRecordViews.drop_all_views connection
273
+ expect(view_names).to match_array %w[]
274
+ end
216
275
  end
217
276
 
218
277
  describe '.without_transaction' do
@@ -1,4 +1,5 @@
1
1
  require 'bundler/setup'
2
+ require './spec/support/silence_warnings.rb'
2
3
  require 'combustion'
3
4
 
4
5
  Combustion::Database.instance_eval do
@@ -10,6 +11,10 @@ end
10
11
  Combustion.initialize! :active_record, :action_controller do
11
12
  config.cache_classes = false
12
13
  config.log_level = :debug
14
+ config.active_record.schema_format = ENV.fetch('SCHEMA_FORMAT', 'sql').to_sym
15
+ if ENV['SKIP_MODEL_EAGER_LOAD']
16
+ config.eager_load_paths -= Rails.application.config.paths['app/models'].to_a
17
+ end
13
18
  end
14
19
 
15
20
  load 'active_record/railties/databases.rake'
@@ -1,3 +1,7 @@
1
1
  class ErbTestModel < ActiveRecord::Base
2
+ def self.test_erb_method
3
+ 'ERB method'
4
+ end
5
+
2
6
  is_view
3
7
  end
@@ -1 +1 @@
1
- SELECT 1 AS id, '<%= "ERB" %> file'::text AS name;
1
+ SELECT 1 AS id, '<%= test_erb_method %> file'::text AS name;
@@ -2,6 +2,7 @@ test: &test
2
2
  adapter: postgresql
3
3
  database: activerecord_views_test
4
4
  min_messages: warning
5
+ advisory_locks: <%= !Rails.version.start_with?('6.0.') %>
5
6
  development:
6
7
  <<: *test
7
8
  production:
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ root to: -> (env) { [204, {}, []] }
3
+ end
data/spec/spec_helper.rb CHANGED
@@ -4,21 +4,52 @@ Bundler.setup
4
4
  require 'rails/version'
5
5
  $VERBOSE = true
6
6
 
7
+ require './spec/support/silence_warnings.rb'
8
+
7
9
  require 'combustion'
8
10
  require 'active_record_views'
9
11
 
10
12
  FileUtils.mkdir_p 'spec/internal/db'
11
13
  File.write 'spec/internal/db/schema.rb', ''
12
14
 
15
+ TEST_TEMP_MODEL_DIR = Rails.root + 'spec/internal/app/models_temp'
16
+ FileUtils.mkdir_p TEST_TEMP_MODEL_DIR
17
+ Rails.application.config.paths['app/models'] << 'app/models_temp'
18
+
13
19
  Combustion.initialize! :active_record, :action_controller do
14
20
  config.cache_classes = false
15
21
  end
16
22
  require 'rspec/rails'
23
+ require 'super_diff/rspec-rails'
24
+
25
+ RSpec.shared_context 'sql_statements' do
26
+ let(:sql_statements) { [] }
27
+
28
+ let!(:sql_statements_subscription) do
29
+ ActiveSupport::Notifications.subscribe('sql.active_record') do |_, _, _, _, details|
30
+ sql_statements << details.fetch(:sql)
31
+ end
32
+ end
33
+
34
+ after do
35
+ ActiveSupport::Notifications.unsubscribe sql_statements_subscription
36
+ end
37
+ end
17
38
 
18
39
  RSpec.configure do |config|
19
40
  config.use_transactional_fixtures = false
41
+ config.filter_run_when_matching focus: true
42
+ config.filter_run_excluding skip: true
43
+ config.example_status_persistence_file_path = 'tmp/examples.txt'
44
+
45
+ config.mock_with :rspec do |mocks|
46
+ mocks.verify_doubled_constant_names = true
47
+ mocks.verify_partial_doubles = true
48
+ end
20
49
 
21
50
  config.before do
51
+ FileUtils.rm_rf Dir["spec/internal/app/models_temp/*"]
52
+
22
53
  if Rails::VERSION::MAJOR >= 5
23
54
  Rails.application.reloader.reload!
24
55
  else
@@ -48,24 +79,27 @@ RSpec.configure do |config|
48
79
  connection.execute "DROP MATERIALIZED VIEW IF EXISTS #{connection.quote_table_name view_name} CASCADE"
49
80
  end
50
81
  end
82
+
83
+ config.include_context 'sql_statements'
51
84
  end
52
85
 
53
- def test_request
54
- begin
55
- Rails.application.call({'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/'})
56
- rescue ActionController::RoutingError
86
+ def with_reloader(&block)
87
+ if Rails.application.respond_to?(:reloader)
88
+ Rails.application.reloader.wrap(&block)
89
+ else
90
+ block.call
57
91
  end
58
92
  end
59
93
 
60
- def with_temp_sql_dir
61
- Dir.mktmpdir do |temp_dir|
62
- begin
63
- old_sql_load_path = ActiveRecordViews.sql_load_path
64
- ActiveRecordViews.sql_load_path = [temp_dir] + old_sql_load_path
65
- yield temp_dir
66
- ensure
67
- ActiveRecordViews.sql_load_path = old_sql_load_path
68
- end
94
+ def test_request
95
+ with_reloader do
96
+ status, headers, body = Rails.application.call(
97
+ 'REQUEST_METHOD' => 'GET',
98
+ 'PATH_INFO' => '/',
99
+ 'rack.input' => StringIO.new,
100
+ )
101
+ expect(status).to eq 204
102
+ body.close
69
103
  end
70
104
  end
71
105
 
@@ -0,0 +1,23 @@
1
+ require 'warning'
2
+ require 'rails/version'
3
+
4
+ case Rails::VERSION::STRING
5
+ when /^4\.2\./
6
+ Warning.ignore(%r{lib/(active_support/core_ext|action_dispatch/middleware)/.+: warning: (method redefined|previous definition)})
7
+ Warning.ignore(%r{lib/active_support/core_ext/.+: warning: BigDecimal.new is deprecated})
8
+ Warning.ignore(%r{lib/arel/visitors/informix.rb:\d+: warning: assigned but unused variable})
9
+ Warning.ignore(%r{lib/active_record/connection_adapters/.+: warning: deprecated Object#=~ is called on Integer})
10
+ Warning.ignore(%r{Inheriting from Rack::Session::Abstract::ID is deprecated})
11
+ when /^5\.0\./
12
+ Warning.ignore(%r{lib/(active_support/core_ext|action_view)/.+: warning: (method redefined|previous definition)})
13
+ Warning.ignore(%r{lib/arel/visitors/informix.rb:\d+: warning: assigned but unused variable})
14
+ Warning.ignore(%r{lib/action_view/.+: warning: `\*' interpreted as argument prefix})
15
+ when /^5\.1\./
16
+ Warning.ignore(%r{lib/(active_support/core_ext)/.+: warning: (method redefined|previous definition)})
17
+ Warning.ignore(%r{lib/arel/visitors/informix.rb:\d+: warning: assigned but unused variable})
18
+ Warning.ignore(%r{lib/active_record/.+/schema_statements.rb:\d+: (warning: in `drop_table': the last argument was passed as a single Hash|warning: although a splat keyword arguments here)})
19
+ end
20
+
21
+ Warning.process do |_warning|
22
+ :raise
23
+ end