activerecord_views 0.0.20 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -228,6 +250,28 @@ describe ActiveRecordViews do
228
250
  create_test_view 'select 1 as foo, 2 as bar, 3 as baz', materialized: false, unique_columns: [:foo, 'bar']
229
251
  }.to raise_error ArgumentError, 'unique_columns option requires view to be materialized'
230
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
231
275
  end
232
276
 
233
277
  describe '.without_transaction' do
@@ -289,5 +333,16 @@ describe ActiveRecordViews do
289
333
  original_connection.pool.checkin original_connection_2
290
334
  end
291
335
  end
336
+
337
+ it 'does not attempt to checkin when checkout fails' do
338
+ expect(original_connection.pool).to receive(:checkout).and_raise PG::ConnectionBad
339
+ expect(original_connection.pool).to_not receive(:checkin)
340
+
341
+ expect {
342
+ original_connection.transaction do
343
+ ActiveRecordViews.without_transaction(original_connection) { }
344
+ end
345
+ }.to raise_error PG::ConnectionBad
346
+ end
292
347
  end
293
348
  end
@@ -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