activerecord_views 0.1.5 → 0.1.7
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.
- 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
|