activerecord_views 0.1.5 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/active_record_views/database_tasks.rb +91 -0
- data/lib/active_record_views/railtie.rb +0 -4
- data/lib/active_record_views/version.rb +1 -1
- data/lib/active_record_views.rb +2 -0
- metadata +11 -65
- data/.gitignore +0 -8
- data/.rspec +0 -2
- data/.tool-versions +0 -1
- data/Appraisals +0 -15
- data/Gemfile +0 -3
- data/LICENSE.txt +0 -22
- data/Rakefile +0 -14
- data/activerecord_views.gemspec +0 -27
- data/gemfiles/rails5_2.gemfile +0 -7
- data/gemfiles/rails6_0.gemfile +0 -7
- data/gemfiles/rails6_1.gemfile +0 -7
- data/gemfiles/rails7_0.gemfile +0 -7
- data/lib/tasks/active_record_views.rake +0 -106
- data/spec/active_record_views_checksum_cache_spec.rb +0 -112
- data/spec/active_record_views_extension_spec.rb +0 -459
- data/spec/active_record_views_spec.rb +0 -344
- data/spec/internal/Rakefile +0 -24
- data/spec/internal/app/models/dependency_a.rb +0 -3
- data/spec/internal/app/models/dependency_b.rb +0 -3
- data/spec/internal/app/models/dependency_c.rb +0 -3
- data/spec/internal/app/models/erb_test_model.rb +0 -7
- data/spec/internal/app/models/erb_test_model.sql.erb +0 -1
- data/spec/internal/app/models/external_file_test_model.rb +0 -3
- data/spec/internal/app/models/external_file_test_model.sql +0 -1
- data/spec/internal/app/models/heredoc_test_model.rb +0 -5
- data/spec/internal/app/models/modified_a.rb +0 -3
- data/spec/internal/app/models/modified_b.rb +0 -3
- data/spec/internal/app/models/namespace/test_model.rb +0 -3
- data/spec/internal/app/models/namespace/test_model.sql +0 -1
- data/spec/internal/config/database.yml +0 -9
- data/spec/internal/config/routes.rb +0 -3
- data/spec/spec_helper.rb +0 -130
- data/spec/support/silence_warnings.rb +0 -6
- data/spec/tasks_spec.rb +0 -113
@@ -1,344 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRecordViews do
|
4
|
-
describe '.create_view' do
|
5
|
-
let(:connection) { ActiveRecord::Base.connection }
|
6
|
-
|
7
|
-
def create_test_view(sql, options = {})
|
8
|
-
ActiveRecordViews.create_view connection, 'test', 'Test', sql, options
|
9
|
-
end
|
10
|
-
|
11
|
-
def drop_test_view
|
12
|
-
ActiveRecordViews.drop_view connection, 'test'
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_view_sql
|
16
|
-
connection.select_value(<<-SQL.squish).try(&:squish)
|
17
|
-
SELECT view_definition
|
18
|
-
FROM information_schema.views
|
19
|
-
WHERE table_schema = 'public' AND table_name = 'test'
|
20
|
-
SQL
|
21
|
-
end
|
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
|
-
value
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_view_refreshed_at
|
34
|
-
connection.select_value(<<~SQL)
|
35
|
-
SELECT refreshed_at
|
36
|
-
FROM active_record_views
|
37
|
-
WHERE name = 'test'
|
38
|
-
SQL
|
39
|
-
end
|
40
|
-
|
41
|
-
def test_materialized_view_sql
|
42
|
-
connection.select_value(<<-SQL.squish).try(&:squish)
|
43
|
-
SELECT definition
|
44
|
-
FROM pg_matviews
|
45
|
-
WHERE schemaname = 'public' AND matviewname = 'test'
|
46
|
-
SQL
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'creates database view' do
|
50
|
-
expect(test_view_sql).to be_nil
|
51
|
-
create_test_view 'select 1 as id'
|
52
|
-
expect(test_view_sql).to eq 'SELECT 1 AS id;'
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'records checksum, class name, and options' do
|
56
|
-
create_test_view 'select 1 as id', materialized: true
|
57
|
-
expect(connection.select_all('select * from active_record_views').to_a).to eq [
|
58
|
-
{
|
59
|
-
'name' => 'test',
|
60
|
-
'class_name' => 'Test',
|
61
|
-
'checksum' => Digest::SHA1.hexdigest('select 1 as id'),
|
62
|
-
'options' => '{"materialized":true,"dependencies":[]}',
|
63
|
-
'refreshed_at' => nil,
|
64
|
-
}
|
65
|
-
]
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'persists views if transaction rolls back' do
|
69
|
-
expect(test_view_sql).to be_nil
|
70
|
-
connection.transaction :requires_new => true do
|
71
|
-
create_test_view 'select 1 as id'
|
72
|
-
raise ActiveRecord::Rollback
|
73
|
-
end
|
74
|
-
expect(test_view_sql).to eq 'SELECT 1 AS id;'
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'raises descriptive error if view SQL is invalid' do
|
78
|
-
expect {
|
79
|
-
create_test_view 'select blah'
|
80
|
-
}.to raise_error ActiveRecord::StatementInvalid, /column "blah" does not exist/
|
81
|
-
end
|
82
|
-
|
83
|
-
context 'with existing view' do
|
84
|
-
before do
|
85
|
-
create_test_view 'select 1 as id'
|
86
|
-
expect(test_view_sql).to eq 'SELECT 1 AS id;'
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'updates view with compatible change' do
|
90
|
-
create_test_view 'select 2 as id'
|
91
|
-
expect(test_view_sql).to eq 'SELECT 2 AS id;'
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'recreates view with incompatible change' do
|
95
|
-
create_test_view "select 'foo'::text as name"
|
96
|
-
expect(test_view_sql).to eq "SELECT 'foo'::text AS name;"
|
97
|
-
end
|
98
|
-
|
99
|
-
context 'having dependant views' do
|
100
|
-
before do
|
101
|
-
without_dependency_checks do
|
102
|
-
ActiveRecordViews.create_view connection, 'dependant1', 'Dependant1', 'SELECT id FROM test;'
|
103
|
-
ActiveRecordViews.create_view connection, 'dependant2a', 'Dependant2a', 'SELECT id, id * 2 AS id2 FROM dependant1;'
|
104
|
-
ActiveRecordViews.create_view connection, 'dependant2b', 'Dependant2b', 'SELECT id, id * 4 AS id4 FROM dependant1;'
|
105
|
-
ActiveRecordViews.create_view connection, 'dependant3', 'Dependant3', 'SELECT * FROM dependant2b;'
|
106
|
-
ActiveRecordViews.create_view connection, 'dependant4', 'Dependant4', 'SELECT id FROM dependant1 UNION ALL SELECT id FROM dependant3;'
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'updates view with compatible change' do
|
111
|
-
create_test_view 'select 2 as id'
|
112
|
-
expect(test_view_sql).to eq 'SELECT 2 AS id;'
|
113
|
-
expect(Integer(connection.select_value('SELECT id2 FROM dependant2a'))).to eq 4
|
114
|
-
end
|
115
|
-
|
116
|
-
describe 'changes incompatible with CREATE OR REPLACE' do
|
117
|
-
it 'updates view with new column added before existing' do
|
118
|
-
create_test_view "select 'foo'::text as name, 3 as id"
|
119
|
-
expect(test_view_sql).to eq "SELECT 'foo'::text AS name, 3 AS id;"
|
120
|
-
expect(Integer(connection.select_value('SELECT id2 FROM dependant2a'))).to eq 6
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'fails to update view if column used by dependant view is removed' do
|
124
|
-
expect {
|
125
|
-
create_test_view "select 'foo'::text as name"
|
126
|
-
}.to raise_error ActiveRecord::StatementInvalid, /column test.id does not exist/
|
127
|
-
expect(test_view_sql).to eq 'SELECT 1 AS id;'
|
128
|
-
expect(Integer(connection.select_value('SELECT id2 FROM dependant2a'))).to eq 2
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
describe '.drop_all_views' do
|
133
|
-
it 'can drop all managed views' do
|
134
|
-
connection.execute 'CREATE VIEW unmanaged AS SELECT 2 AS id;'
|
135
|
-
|
136
|
-
expect(view_names).to match_array %w[test dependant1 dependant2a dependant2b dependant3 dependant4 unmanaged]
|
137
|
-
ActiveRecordViews.drop_all_views connection
|
138
|
-
expect(view_names).to match_array %w[unmanaged]
|
139
|
-
end
|
140
|
-
|
141
|
-
it 'support being ran inside a transaction' do
|
142
|
-
expect(ActiveRecordViews).to receive(:without_transaction).at_least(:once).and_wrap_original do |original, *args, &block|
|
143
|
-
original.call(*args) do |new_connection|
|
144
|
-
new_connection.execute 'SET statement_timeout = 1000'
|
145
|
-
block.call(new_connection)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
connection.transaction requires_new: true do
|
150
|
-
expect {
|
151
|
-
ActiveRecordViews.drop_all_views connection
|
152
|
-
}.to change { view_names }
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'errors if an unmanaged view depends on a managed view' do
|
157
|
-
connection.execute 'CREATE VIEW unmanaged AS SELECT * from dependant2a'
|
158
|
-
|
159
|
-
expect {
|
160
|
-
ActiveRecordViews.drop_all_views connection
|
161
|
-
}.to raise_error ActiveRecord::StatementInvalid, /view unmanaged depends on view dependant2a/
|
162
|
-
end
|
163
|
-
|
164
|
-
it 'can drop materialized views' do
|
165
|
-
without_dependency_checks do
|
166
|
-
ActiveRecordViews.create_view connection, 'materialized', 'Materialized', 'SELECT id FROM test;', materialized: true
|
167
|
-
end
|
168
|
-
ActiveRecordViews.drop_all_views connection
|
169
|
-
expect(view_names).to match_array %w[]
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
describe 'with unmanaged dependant view' do
|
175
|
-
before do
|
176
|
-
connection.execute 'CREATE VIEW dependant AS SELECT id FROM test'
|
177
|
-
end
|
178
|
-
|
179
|
-
after do
|
180
|
-
connection.execute 'DROP VIEW dependant;'
|
181
|
-
end
|
182
|
-
|
183
|
-
it 'updates view with compatible change' do
|
184
|
-
create_test_view 'select 2 as id'
|
185
|
-
expect(test_view_sql).to eq 'SELECT 2 AS id;'
|
186
|
-
end
|
187
|
-
|
188
|
-
it 'fails to update view with incompatible change' do
|
189
|
-
expect {
|
190
|
-
create_test_view "SELECT 'foo'::text as name, 4 as id"
|
191
|
-
}.to raise_error ActiveRecord::StatementInvalid, /view dependant depends on view test/
|
192
|
-
expect(test_view_sql).to eq 'SELECT 1 AS id;'
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
it 'creates and drops materialized views' do
|
198
|
-
create_test_view 'select 123 as id', materialized: true
|
199
|
-
expect(test_view_sql).to eq nil
|
200
|
-
expect(test_materialized_view_sql).to eq 'SELECT 123 AS id;'
|
201
|
-
|
202
|
-
drop_test_view
|
203
|
-
expect(test_view_sql).to eq nil
|
204
|
-
expect(test_materialized_view_sql).to eq nil
|
205
|
-
end
|
206
|
-
|
207
|
-
it 'replaces a normal view with a materialized view' do
|
208
|
-
create_test_view 'select 11 as id'
|
209
|
-
create_test_view 'select 22 as id', materialized: true
|
210
|
-
|
211
|
-
expect(test_view_sql).to eq nil
|
212
|
-
expect(test_materialized_view_sql).to eq 'SELECT 22 AS id;'
|
213
|
-
end
|
214
|
-
|
215
|
-
it 'replaces a materialized view with a normal view' do
|
216
|
-
create_test_view 'select 22 as id', materialized: true
|
217
|
-
create_test_view 'select 11 as id'
|
218
|
-
|
219
|
-
expect(test_view_sql).to eq 'SELECT 11 AS id;'
|
220
|
-
expect(test_materialized_view_sql).to eq nil
|
221
|
-
end
|
222
|
-
|
223
|
-
it 'can test if materialized views can be refreshed concurrently' do
|
224
|
-
expect(ActiveRecordViews.supports_concurrent_refresh?(connection)).to be true
|
225
|
-
end
|
226
|
-
|
227
|
-
it 'preserves materialized view if dropping/recreating' do
|
228
|
-
without_dependency_checks do
|
229
|
-
ActiveRecordViews.create_view connection, 'test1', 'Test1', 'SELECT 1 AS foo'
|
230
|
-
ActiveRecordViews.create_view connection, 'test2', 'Test2', 'SELECT * FROM test1', materialized: true
|
231
|
-
ActiveRecordViews.create_view connection, 'test1', 'Test1', 'SELECT 2 AS bar, 1 AS foo'
|
232
|
-
end
|
233
|
-
|
234
|
-
expect(materialized_view_names).to eq %w[test2]
|
235
|
-
expect(view_names).to eq %w[test1]
|
236
|
-
end
|
237
|
-
|
238
|
-
it 'supports creating unique indexes on materialized views' do
|
239
|
-
create_test_view 'select 1 as foo, 2 as bar, 3 as baz', materialized: true, unique_columns: [:foo, 'bar']
|
240
|
-
index_sql = connection.select_value("SELECT indexdef FROM pg_indexes WHERE schemaname = 'public' AND indexname = 'test_pkey';")
|
241
|
-
expect(index_sql).to eq 'CREATE UNIQUE INDEX test_pkey ON public.test USING btree (foo, bar)'
|
242
|
-
end
|
243
|
-
|
244
|
-
it 'errors if trying to create unique index on non-materialized view' do
|
245
|
-
expect {
|
246
|
-
create_test_view 'select 1 as foo, 2 as bar, 3 as baz', materialized: false, unique_columns: [:foo, 'bar']
|
247
|
-
}.to raise_error ArgumentError, 'unique_columns option requires view to be materialized'
|
248
|
-
end
|
249
|
-
|
250
|
-
it 'supports resetting all materialised views' do
|
251
|
-
class ResetMaterializeViewTestModel < ActiveRecord::Base
|
252
|
-
self.table_name = 'test'
|
253
|
-
is_view 'select 123 as id', materialized: true
|
254
|
-
end
|
255
|
-
ResetMaterializeViewTestModel.refresh_view!
|
256
|
-
|
257
|
-
expect {
|
258
|
-
ActiveRecordViews.reset_materialized_views
|
259
|
-
}.to change { test_view_populated? }.to(false)
|
260
|
-
.and change { test_view_refreshed_at }.to(nil)
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
describe '.drop_all_views' do
|
265
|
-
let(:connection) { ActiveRecord::Base.connection }
|
266
|
-
|
267
|
-
it 'does nothing when no views have been defined' do
|
268
|
-
ActiveRecordViews.drop_all_views connection
|
269
|
-
expect(view_names).to match_array %w[]
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
describe '.without_transaction' do
|
274
|
-
let(:original_connection) { ActiveRecord::Base.connection }
|
275
|
-
|
276
|
-
it 'yields original connection if no active transaction' do
|
277
|
-
ActiveRecordViews.without_transaction original_connection do |new_connection|
|
278
|
-
expect(new_connection).to eq original_connection
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
it 'yields a new connection if inside a transaction' do
|
283
|
-
original_connection.transaction do
|
284
|
-
ActiveRecordViews.without_transaction original_connection do |new_connection|
|
285
|
-
expect(new_connection).to_not eq original_connection
|
286
|
-
end
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
it 'yields original connection if called recursively' do
|
291
|
-
ActiveRecordViews.without_transaction original_connection do |new_connection_1|
|
292
|
-
expect(new_connection_1).to eq original_connection
|
293
|
-
new_connection_1.transaction do
|
294
|
-
ActiveRecordViews.without_transaction new_connection_1 do |new_connection_2|
|
295
|
-
expect(new_connection_2).to eq new_connection_1
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
it 'yields same isolated connection if called recursively on original connection inside transaction' do
|
302
|
-
original_connection.transaction do
|
303
|
-
ActiveRecordViews.without_transaction original_connection do |new_connection_1|
|
304
|
-
expect(new_connection_1).to_not eq original_connection
|
305
|
-
ActiveRecordViews.without_transaction original_connection do |new_connection_2|
|
306
|
-
expect(new_connection_2).to eq new_connection_1
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
it 'yields different isolated connection if called recursively on different connections inside transcation' do
|
313
|
-
begin
|
314
|
-
original_connection_2 = original_connection.pool.checkout
|
315
|
-
|
316
|
-
original_connection.transaction do
|
317
|
-
ActiveRecordViews.without_transaction original_connection do |new_connection_1|
|
318
|
-
expect(new_connection_1).to_not eq original_connection
|
319
|
-
original_connection_2.transaction do
|
320
|
-
ActiveRecordViews.without_transaction original_connection_2 do |new_connection_2|
|
321
|
-
expect(new_connection_2).to_not eq original_connection
|
322
|
-
expect(new_connection_2).to_not eq original_connection_2
|
323
|
-
expect(new_connection_2).to_not eq new_connection_1
|
324
|
-
end
|
325
|
-
end
|
326
|
-
end
|
327
|
-
end
|
328
|
-
ensure
|
329
|
-
original_connection.pool.checkin original_connection_2
|
330
|
-
end
|
331
|
-
end
|
332
|
-
|
333
|
-
it 'does not attempt to checkin when checkout fails' do
|
334
|
-
expect(original_connection.pool).to receive(:checkout).and_raise PG::ConnectionBad
|
335
|
-
expect(original_connection.pool).to_not receive(:checkin)
|
336
|
-
|
337
|
-
expect {
|
338
|
-
original_connection.transaction do
|
339
|
-
ActiveRecordViews.without_transaction(original_connection) { }
|
340
|
-
end
|
341
|
-
}.to raise_error PG::ConnectionBad
|
342
|
-
end
|
343
|
-
end
|
344
|
-
end
|
data/spec/internal/Rakefile
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'bundler/setup'
|
2
|
-
require './spec/support/silence_warnings.rb'
|
3
|
-
require 'combustion'
|
4
|
-
|
5
|
-
Combustion::Database.instance_eval do
|
6
|
-
def setup(options)
|
7
|
-
ActiveRecord::Base.configurations = YAML.load(ERB.new(File.read("#{Rails.root}/config/database.yml")).result)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
Combustion.initialize! :active_record, :action_controller do
|
12
|
-
config.cache_classes = false
|
13
|
-
config.log_level = :debug
|
14
|
-
config.active_record.schema_format = ENV.fetch('SCHEMA_FORMAT', 'sql').to_sym
|
15
|
-
if Gem::Version.new(Rails.version) >= Gem::Version.new("6.1")
|
16
|
-
config.active_record.legacy_connection_handling = false
|
17
|
-
end
|
18
|
-
if ENV['SKIP_MODEL_EAGER_LOAD']
|
19
|
-
config.eager_load_paths -= Rails.application.config.paths['app/models'].to_a
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
load 'active_record/railties/databases.rake'
|
24
|
-
Combustion::Application.load_tasks
|
@@ -1 +0,0 @@
|
|
1
|
-
SELECT 1 AS id, '<%= test_erb_method %> file'::text AS name;
|
@@ -1 +0,0 @@
|
|
1
|
-
SELECT 1 AS id, 'External SQL file'::text AS name;
|
@@ -1 +0,0 @@
|
|
1
|
-
SELECT 1 AS id, 'Namespaced SQL file'::text AS name;
|
data/spec/spec_helper.rb
DELETED
@@ -1,130 +0,0 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
Bundler.setup
|
3
|
-
|
4
|
-
require 'rails/version'
|
5
|
-
$VERBOSE = true
|
6
|
-
|
7
|
-
require './spec/support/silence_warnings.rb'
|
8
|
-
|
9
|
-
require 'combustion'
|
10
|
-
require 'active_record_views'
|
11
|
-
|
12
|
-
FileUtils.mkdir_p 'spec/internal/db'
|
13
|
-
File.write 'spec/internal/db/schema.rb', ''
|
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
|
-
|
19
|
-
Combustion.initialize! :active_record, :action_controller do
|
20
|
-
config.cache_classes = false
|
21
|
-
config.secret_key_base = 'dummy'
|
22
|
-
if Gem::Version.new(Rails.version) >= Gem::Version.new("6.1")
|
23
|
-
config.active_record.legacy_connection_handling = false
|
24
|
-
end
|
25
|
-
end
|
26
|
-
require 'rspec/rails'
|
27
|
-
|
28
|
-
RSpec.shared_context 'sql_statements' do
|
29
|
-
let(:sql_statements) { [] }
|
30
|
-
|
31
|
-
let!(:sql_statements_subscription) do
|
32
|
-
ActiveSupport::Notifications.subscribe('sql.active_record') do |_, _, _, _, details|
|
33
|
-
sql_statements << details.fetch(:sql)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
after do
|
38
|
-
ActiveSupport::Notifications.unsubscribe sql_statements_subscription
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
RSpec.configure do |config|
|
43
|
-
config.use_transactional_fixtures = false
|
44
|
-
config.filter_run_when_matching focus: true
|
45
|
-
config.filter_run_excluding skip: true
|
46
|
-
config.example_status_persistence_file_path = 'tmp/examples.txt'
|
47
|
-
|
48
|
-
config.mock_with :rspec do |mocks|
|
49
|
-
mocks.verify_doubled_constant_names = true
|
50
|
-
mocks.verify_partial_doubles = true
|
51
|
-
end
|
52
|
-
|
53
|
-
config.before do
|
54
|
-
FileUtils.rm_rf Dir["spec/internal/app/models_temp/*"]
|
55
|
-
|
56
|
-
Rails.application.reloader.reload!
|
57
|
-
|
58
|
-
connection = ActiveRecord::Base.connection
|
59
|
-
|
60
|
-
connection.execute 'DROP TABLE IF EXISTS active_record_views'
|
61
|
-
|
62
|
-
view_names = connection.select_values(<<-SQL.squish)
|
63
|
-
SELECT table_name
|
64
|
-
FROM information_schema.views
|
65
|
-
WHERE table_schema = 'public';
|
66
|
-
SQL
|
67
|
-
view_names.each do |view_name|
|
68
|
-
connection.execute "DROP VIEW IF EXISTS #{connection.quote_table_name view_name} CASCADE"
|
69
|
-
end
|
70
|
-
|
71
|
-
materialized_view_names = connection.select_values(<<-SQL.squish)
|
72
|
-
SELECT matviewname
|
73
|
-
FROM pg_matviews
|
74
|
-
WHERE schemaname = 'public'
|
75
|
-
SQL
|
76
|
-
materialized_view_names.each do |view_name|
|
77
|
-
connection.execute "DROP MATERIALIZED VIEW IF EXISTS #{connection.quote_table_name view_name} CASCADE"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
config.include_context 'sql_statements'
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_request
|
85
|
-
status, headers, body = Rails.application.call(
|
86
|
-
'REQUEST_METHOD' => 'GET',
|
87
|
-
'PATH_INFO' => '/',
|
88
|
-
'rack.input' => StringIO.new,
|
89
|
-
)
|
90
|
-
expect(status).to eq 204
|
91
|
-
body.close
|
92
|
-
end
|
93
|
-
|
94
|
-
def update_file(file, new_content)
|
95
|
-
time = File.exist?(file) ? File.mtime(file) : Time.parse('2012-01-01')
|
96
|
-
time = time + 1
|
97
|
-
File.write file, new_content
|
98
|
-
File.utime time, time, file
|
99
|
-
end
|
100
|
-
|
101
|
-
def view_names
|
102
|
-
ActiveRecord::Base.connection.select_values(<<-SQL.squish)
|
103
|
-
SELECT table_name
|
104
|
-
FROM information_schema.views
|
105
|
-
WHERE table_schema = 'public'
|
106
|
-
SQL
|
107
|
-
end
|
108
|
-
|
109
|
-
def materialized_view_names
|
110
|
-
ActiveRecord::Base.connection.select_values(<<-SQL.squish)
|
111
|
-
SELECT matviewname
|
112
|
-
FROM pg_matviews
|
113
|
-
WHERE schemaname = 'public'
|
114
|
-
SQL
|
115
|
-
end
|
116
|
-
|
117
|
-
def without_dependency_checks
|
118
|
-
allow(ActiveRecordViews).to receive(:check_dependencies)
|
119
|
-
yield
|
120
|
-
ensure
|
121
|
-
allow(ActiveRecordViews).to receive(:check_dependencies).and_call_original
|
122
|
-
end
|
123
|
-
|
124
|
-
def without_create_enabled
|
125
|
-
old_enabled = ActiveRecordViews::Extension.create_enabled
|
126
|
-
ActiveRecordViews::Extension.create_enabled = false
|
127
|
-
yield
|
128
|
-
ensure
|
129
|
-
ActiveRecordViews::Extension.create_enabled = old_enabled
|
130
|
-
end
|