scenic 1.8.0 → 1.9.0
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/.github/workflows/ci.yml +13 -8
- data/.gitignore +1 -0
- data/CHANGELOG.md +48 -19
- data/FUNDING.yml +1 -0
- data/Gemfile +2 -2
- data/README.md +71 -18
- data/lib/generators/scenic/materializable.rb +27 -1
- data/lib/generators/scenic/view/templates/db/migrate/update_view.erb +1 -1
- data/lib/scenic/adapters/postgres/index_creation.rb +68 -0
- data/lib/scenic/adapters/postgres/index_migration.rb +70 -0
- data/lib/scenic/adapters/postgres/index_reapplication.rb +3 -28
- data/lib/scenic/adapters/postgres/side_by_side.rb +50 -0
- data/lib/scenic/adapters/postgres/temporary_name.rb +34 -0
- data/lib/scenic/adapters/postgres/views.rb +83 -10
- data/lib/scenic/adapters/postgres.rb +41 -18
- data/lib/scenic/schema_dumper.rb +0 -14
- data/lib/scenic/statements.rb +46 -13
- data/lib/scenic/version.rb +1 -1
- data/scenic.gemspec +5 -1
- data/spec/acceptance/user_manages_views_spec.rb +11 -0
- data/spec/dummy/config/application.rb +4 -0
- data/spec/generators/scenic/view/view_generator_spec.rb +26 -0
- data/spec/scenic/adapters/postgres/index_creation_spec.rb +54 -0
- data/spec/scenic/adapters/postgres/index_migration_spec.rb +24 -0
- data/spec/scenic/adapters/postgres/side_by_side_spec.rb +24 -0
- data/spec/scenic/adapters/postgres/temporary_name_spec.rb +23 -0
- data/spec/scenic/adapters/postgres_spec.rb +44 -3
- data/spec/scenic/command_recorder_spec.rb +18 -0
- data/spec/scenic/schema_dumper_spec.rb +29 -8
- data/spec/scenic/statements_spec.rb +62 -4
- data/spec/spec_helper.rb +19 -4
- data/spec/support/database_schema_helpers.rb +28 -0
- metadata +19 -11
@@ -0,0 +1,24 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Scenic
|
4
|
+
module Adapters
|
5
|
+
describe Postgres::IndexMigration, :db, :silence do
|
6
|
+
it "moves indexes from the old view to the new view" do
|
7
|
+
create_materialized_view("hi", "SELECT 'hi' AS greeting")
|
8
|
+
create_materialized_view("hi_temp", "SELECT 'hi' AS greeting")
|
9
|
+
add_index(:hi, :greeting, name: "hi_greeting_idx")
|
10
|
+
|
11
|
+
Postgres::IndexMigration
|
12
|
+
.new(connection: ActiveRecord::Base.connection)
|
13
|
+
.migrate(from: "hi", to: "hi_temp")
|
14
|
+
indexes_for_original = indexes_for("hi")
|
15
|
+
indexes_for_temporary = indexes_for("hi_temp")
|
16
|
+
|
17
|
+
expect(indexes_for_original.length).to eq 1
|
18
|
+
expect(indexes_for_original.first.index_name).not_to eq "hi_greeting_idx"
|
19
|
+
expect(indexes_for_temporary.length).to eq 1
|
20
|
+
expect(indexes_for_temporary.first.index_name).to eq "hi_greeting_idx"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Scenic
|
4
|
+
module Adapters
|
5
|
+
describe Postgres::SideBySide, :db, :silence do
|
6
|
+
it "updates the materialized view to the new version" do
|
7
|
+
adapter = Postgres.new
|
8
|
+
create_materialized_view("hi", "SELECT 'hi' AS greeting")
|
9
|
+
add_index(:hi, :greeting, name: "hi_greeting_idx")
|
10
|
+
new_definition = "SELECT 'hola' AS greeting"
|
11
|
+
|
12
|
+
Postgres::SideBySide
|
13
|
+
.new(adapter: adapter, name: "hi", definition: new_definition)
|
14
|
+
.update
|
15
|
+
result = ar_connection.execute("SELECT * FROM hi").first["greeting"]
|
16
|
+
indexes = indexes_for("hi")
|
17
|
+
|
18
|
+
expect(result).to eq "hola"
|
19
|
+
expect(indexes.length).to eq 1
|
20
|
+
expect(indexes.first.index_name).to eq "hi_greeting_idx"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Scenic
|
4
|
+
module Adapters
|
5
|
+
describe Postgres::TemporaryName do
|
6
|
+
it "generates a temporary name based on a SHA1 hash of the original" do
|
7
|
+
name = "my_materialized_view"
|
8
|
+
|
9
|
+
temporary_name = Postgres::TemporaryName.new(name).to_s
|
10
|
+
|
11
|
+
expect(temporary_name).to match(/_scenic_sbs_[0-9a-f]{40}/)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "does not overflow the 63 character limit for object names" do
|
15
|
+
name = "long_view_name_" * 10
|
16
|
+
|
17
|
+
temporary_name = Postgres::TemporaryName.new(name).to_s
|
18
|
+
|
19
|
+
expect(temporary_name.length).to eq 52
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -149,6 +149,14 @@ module Scenic
|
|
149
149
|
adapter.refresh_materialized_view(:tests, concurrently: true)
|
150
150
|
}.to raise_error e
|
151
151
|
end
|
152
|
+
|
153
|
+
it "falls back to non-concurrent refresh if not populated" do
|
154
|
+
adapter = Postgres.new
|
155
|
+
adapter.create_materialized_view(:testing, "SELECT unnest('{1, 2}'::int[])", no_data: true)
|
156
|
+
|
157
|
+
expect { adapter.refresh_materialized_view(:testing, concurrently: true) }
|
158
|
+
.not_to raise_error
|
159
|
+
end
|
152
160
|
end
|
153
161
|
end
|
154
162
|
|
@@ -176,8 +184,8 @@ module Scenic
|
|
176
184
|
SQL
|
177
185
|
|
178
186
|
expect(adapter.views.map(&:name)).to eq [
|
179
|
-
"parents",
|
180
187
|
"children",
|
188
|
+
"parents",
|
181
189
|
"people",
|
182
190
|
"people_with_names"
|
183
191
|
]
|
@@ -193,13 +201,13 @@ module Scenic
|
|
193
201
|
|
194
202
|
ActiveRecord::Base.connection.execute <<-SQL
|
195
203
|
CREATE SCHEMA scenic;
|
196
|
-
CREATE VIEW scenic.
|
204
|
+
CREATE VIEW scenic.more_parents AS SELECT text 'Maarten' AS name;
|
197
205
|
SET search_path TO scenic, public;
|
198
206
|
SQL
|
199
207
|
|
200
208
|
expect(adapter.views.map(&:name)).to eq [
|
201
209
|
"parents",
|
202
|
-
"scenic.
|
210
|
+
"scenic.more_parents"
|
203
211
|
]
|
204
212
|
end
|
205
213
|
end
|
@@ -250,6 +258,39 @@ module Scenic
|
|
250
258
|
expect { adapter.populated?("greetings") }.to raise_error err
|
251
259
|
end
|
252
260
|
end
|
261
|
+
|
262
|
+
describe "#update_materialized_view" do
|
263
|
+
it "updates the definition of a materialized view in place" do
|
264
|
+
adapter = Postgres.new
|
265
|
+
create_materialized_view("hi", "SELECT 'hi' AS greeting")
|
266
|
+
new_definition = "SELECT 'hello' AS greeting"
|
267
|
+
|
268
|
+
adapter.update_materialized_view("hi", new_definition)
|
269
|
+
result = adapter.connection.execute("SELECT * FROM hi").first["greeting"]
|
270
|
+
|
271
|
+
expect(result).to eq "hello"
|
272
|
+
end
|
273
|
+
|
274
|
+
it "updates the definition of a materialized view side by side", :silence do
|
275
|
+
adapter = Postgres.new
|
276
|
+
create_materialized_view("hi", "SELECT 'hi' AS greeting")
|
277
|
+
new_definition = "SELECT 'hello' AS greeting"
|
278
|
+
|
279
|
+
adapter.update_materialized_view("hi", new_definition, side_by_side: true)
|
280
|
+
result = adapter.connection.execute("SELECT * FROM hi").first["greeting"]
|
281
|
+
|
282
|
+
expect(result).to eq "hello"
|
283
|
+
end
|
284
|
+
|
285
|
+
it "raises an exception if the version of PostgreSQL is too old" do
|
286
|
+
connection = double("Connection", supports_materialized_views?: false)
|
287
|
+
connectable = double("Connectable", connection: connection)
|
288
|
+
adapter = Postgres.new(connectable)
|
289
|
+
|
290
|
+
expect { adapter.create_materialized_view("greetings", "select 1") }
|
291
|
+
.to raise_error Postgres::MaterializedViewsNotSupportedError
|
292
|
+
end
|
293
|
+
end
|
253
294
|
end
|
254
295
|
end
|
255
296
|
end
|
@@ -77,6 +77,24 @@ describe Scenic::CommandRecorder do
|
|
77
77
|
expect { recorder.revert { recorder.update_view(*args) } }
|
78
78
|
.to raise_error(ActiveRecord::IrreversibleMigration)
|
79
79
|
end
|
80
|
+
|
81
|
+
it "reverts materialized views with no_data option appropriately" do
|
82
|
+
args = [:users, {version: 2, revert_to_version: 1, materialized: {no_data: true}}]
|
83
|
+
revert_args = [:users, {version: 1, materialized: {no_data: true}}]
|
84
|
+
|
85
|
+
recorder.revert { recorder.update_view(*args) }
|
86
|
+
|
87
|
+
expect(recorder.commands).to eq [[:update_view, revert_args]]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "reverts materialized views with side_by_side option appropriately" do
|
91
|
+
args = [:users, {version: 2, revert_to_version: 1, materialized: {side_by_side: true}}]
|
92
|
+
revert_args = [:users, {version: 1, materialized: {side_by_side: true}}]
|
93
|
+
|
94
|
+
recorder.revert { recorder.update_view(*args) }
|
95
|
+
|
96
|
+
expect(recorder.commands).to eq [[:update_view, revert_args]]
|
97
|
+
end
|
80
98
|
end
|
81
99
|
|
82
100
|
describe "#replace_view" do
|
@@ -12,7 +12,7 @@ describe Scenic::SchemaDumper, :db do
|
|
12
12
|
Search.connection.create_view :searches, sql_definition: view_definition
|
13
13
|
stream = StringIO.new
|
14
14
|
|
15
|
-
|
15
|
+
dump_schema(stream)
|
16
16
|
|
17
17
|
output = stream.string
|
18
18
|
|
@@ -31,7 +31,7 @@ describe Scenic::SchemaDumper, :db do
|
|
31
31
|
Search.connection.create_view :searches, sql_definition: view_definition
|
32
32
|
stream = StringIO.new
|
33
33
|
|
34
|
-
|
34
|
+
dump_schema(stream)
|
35
35
|
|
36
36
|
output = stream.string
|
37
37
|
expect(output).to include "~ '\\\\d+'::text"
|
@@ -47,7 +47,7 @@ describe Scenic::SchemaDumper, :db do
|
|
47
47
|
Search.connection.create_view :searches, materialized: true, sql_definition: view_definition
|
48
48
|
stream = StringIO.new
|
49
49
|
|
50
|
-
|
50
|
+
dump_schema(stream)
|
51
51
|
|
52
52
|
output = stream.string
|
53
53
|
|
@@ -62,13 +62,29 @@ describe Scenic::SchemaDumper, :db do
|
|
62
62
|
Search.connection.create_view :"scenic.searches", sql_definition: view_definition
|
63
63
|
stream = StringIO.new
|
64
64
|
|
65
|
-
|
65
|
+
dump_schema(stream)
|
66
66
|
|
67
67
|
output = stream.string
|
68
68
|
expect(output).to include 'create_view "scenic.searches",'
|
69
69
|
|
70
70
|
Search.connection.drop_view :"scenic.searches"
|
71
71
|
end
|
72
|
+
|
73
|
+
it "sorts dependency order when views exist in a non-public schema" do
|
74
|
+
Search.connection.execute("CREATE SCHEMA IF NOT EXISTS scenic; SET search_path TO public, scenic")
|
75
|
+
Search.connection.execute("CREATE VIEW scenic.apples AS SELECT 1;")
|
76
|
+
Search.connection.execute("CREATE VIEW scenic.bananas AS SELECT 2;")
|
77
|
+
Search.connection.execute("CREATE OR REPLACE VIEW scenic.apples AS SELECT * FROM scenic.bananas;")
|
78
|
+
stream = StringIO.new
|
79
|
+
|
80
|
+
dump_schema(stream)
|
81
|
+
views = stream.string.lines.grep(/create_view/).map do |view_line|
|
82
|
+
view_line.match('create_view "(?<name>.*)"')[:name]
|
83
|
+
end
|
84
|
+
expect(views).to eq(%w[scenic.bananas scenic.apples])
|
85
|
+
|
86
|
+
Search.connection.execute("DROP SCHEMA IF EXISTS scenic CASCADE; SET search_path TO public")
|
87
|
+
end
|
72
88
|
end
|
73
89
|
|
74
90
|
it "handles active record table name prefixes and suffixes" do
|
@@ -77,7 +93,7 @@ describe Scenic::SchemaDumper, :db do
|
|
77
93
|
Search.connection.create_view :a_searches_z, sql_definition: view_definition
|
78
94
|
stream = StringIO.new
|
79
95
|
|
80
|
-
|
96
|
+
dump_schema(stream)
|
81
97
|
|
82
98
|
output = stream.string
|
83
99
|
|
@@ -90,7 +106,7 @@ describe Scenic::SchemaDumper, :db do
|
|
90
106
|
Search.connection.create_view :searches, sql_definition: view_definition
|
91
107
|
stream = StringIO.new
|
92
108
|
|
93
|
-
|
109
|
+
dump_schema(stream)
|
94
110
|
|
95
111
|
output = stream.string
|
96
112
|
|
@@ -105,7 +121,7 @@ describe Scenic::SchemaDumper, :db do
|
|
105
121
|
Search.connection.create_view '"search in a haystack"', sql_definition: view_definition
|
106
122
|
stream = StringIO.new
|
107
123
|
|
108
|
-
|
124
|
+
dump_schema(stream)
|
109
125
|
|
110
126
|
output = stream.string
|
111
127
|
expect(output).to include 'create_view "\"search in a haystack\"",'
|
@@ -129,7 +145,7 @@ describe Scenic::SchemaDumper, :db do
|
|
129
145
|
sql_definition: view_definition
|
130
146
|
stream = StringIO.new
|
131
147
|
|
132
|
-
|
148
|
+
dump_schema(stream)
|
133
149
|
|
134
150
|
output = stream.string
|
135
151
|
expect(output).to include 'create_view "scenic.\"search in a haystack\"",'
|
@@ -137,6 +153,11 @@ describe Scenic::SchemaDumper, :db do
|
|
137
153
|
|
138
154
|
Search.connection.drop_view :'scenic."search in a haystack"'
|
139
155
|
|
156
|
+
case ActiveRecord.gem_version
|
157
|
+
when Gem::Requirement.new(">= 7.1")
|
158
|
+
Search.connection.drop_schema "scenic"
|
159
|
+
end
|
160
|
+
|
140
161
|
silence_stream($stdout) { eval(output) } # standard:disable Security/Eval
|
141
162
|
|
142
163
|
expect(SearchInAHaystack.take.haystack).to eq "needle"
|
@@ -125,7 +125,7 @@ module Scenic
|
|
125
125
|
connection.update_view(:name, version: 3, materialized: true)
|
126
126
|
|
127
127
|
expect(Scenic.database).to have_received(:update_materialized_view)
|
128
|
-
.with(:name, definition.to_sql, no_data: false)
|
128
|
+
.with(:name, definition.to_sql, no_data: false, side_by_side: false)
|
129
129
|
end
|
130
130
|
|
131
131
|
it "updates the materialized view in the database with NO DATA" do
|
@@ -141,7 +141,23 @@ module Scenic
|
|
141
141
|
)
|
142
142
|
|
143
143
|
expect(Scenic.database).to have_received(:update_materialized_view)
|
144
|
-
.with(:name, definition.to_sql, no_data: true)
|
144
|
+
.with(:name, definition.to_sql, no_data: true, side_by_side: false)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "updates the materialized view with side-by-side mode" do
|
148
|
+
definition = instance_double("Definition", to_sql: "definition")
|
149
|
+
allow(Definition).to receive(:new)
|
150
|
+
.with(:name, 3)
|
151
|
+
.and_return(definition)
|
152
|
+
|
153
|
+
connection.update_view(
|
154
|
+
:name,
|
155
|
+
version: 3,
|
156
|
+
materialized: {side_by_side: true}
|
157
|
+
)
|
158
|
+
|
159
|
+
expect(Scenic.database).to have_received(:update_materialized_view)
|
160
|
+
.with(:name, definition.to_sql, no_data: false, side_by_side: true)
|
145
161
|
end
|
146
162
|
|
147
163
|
it "raises an error if not supplied a version or sql_defintion" do
|
@@ -160,6 +176,36 @@ module Scenic
|
|
160
176
|
)
|
161
177
|
end.to raise_error ArgumentError, /cannot both be set/
|
162
178
|
end
|
179
|
+
|
180
|
+
it "raises an error is no_data and side_by_side are both set" do
|
181
|
+
definition = instance_double("Definition", to_sql: "definition")
|
182
|
+
allow(Definition).to receive(:new)
|
183
|
+
.with(:name, 3)
|
184
|
+
.and_return(definition)
|
185
|
+
|
186
|
+
expect do
|
187
|
+
connection.update_view(
|
188
|
+
:name,
|
189
|
+
version: 3,
|
190
|
+
materialized: {no_data: true, side_by_side: true}
|
191
|
+
)
|
192
|
+
end.to raise_error ArgumentError, /cannot be combined/
|
193
|
+
end
|
194
|
+
|
195
|
+
it "raises an error if not in a transaction" do
|
196
|
+
definition = instance_double("Definition", to_sql: "definition")
|
197
|
+
allow(Definition).to receive(:new)
|
198
|
+
.with(:name, 3)
|
199
|
+
.and_return(definition)
|
200
|
+
|
201
|
+
expect do
|
202
|
+
connection(transactions_enabled: false).update_view(
|
203
|
+
:name,
|
204
|
+
version: 3,
|
205
|
+
materialized: {side_by_side: true}
|
206
|
+
)
|
207
|
+
end.to raise_error RuntimeError, /transaction is required/
|
208
|
+
end
|
163
209
|
end
|
164
210
|
|
165
211
|
describe "replace_view" do
|
@@ -192,8 +238,20 @@ module Scenic
|
|
192
238
|
end
|
193
239
|
end
|
194
240
|
|
195
|
-
def connection
|
196
|
-
|
241
|
+
def connection(transactions_enabled: true)
|
242
|
+
DummyConnection.new(transactions_enabled: transactions_enabled)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
class DummyConnection
|
247
|
+
include Statements
|
248
|
+
|
249
|
+
def initialize(transactions_enabled:)
|
250
|
+
@transactions_enabled = transactions_enabled
|
251
|
+
end
|
252
|
+
|
253
|
+
def transaction_open?
|
254
|
+
@transactions_enabled
|
197
255
|
end
|
198
256
|
end
|
199
257
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,24 +2,39 @@ ENV["RAILS_ENV"] = "test"
|
|
2
2
|
require "database_cleaner"
|
3
3
|
|
4
4
|
require File.expand_path("dummy/config/environment", __dir__)
|
5
|
-
|
6
|
-
|
7
|
-
require "support/view_definition_helpers"
|
5
|
+
|
6
|
+
Dir.glob("#{__dir__}/support/**/*.rb").each { |f| require f }
|
8
7
|
|
9
8
|
RSpec.configure do |config|
|
10
9
|
config.order = "random"
|
10
|
+
config.include DatabaseSchemaHelpers
|
11
11
|
config.include ViewDefinitionHelpers
|
12
12
|
config.include RailsConfigurationHelpers
|
13
13
|
DatabaseCleaner.strategy = :transaction
|
14
14
|
|
15
15
|
config.around(:each, db: true) do |example|
|
16
|
-
ActiveRecord
|
16
|
+
case ActiveRecord.gem_version
|
17
|
+
when Gem::Requirement.new(">= 7.2")
|
18
|
+
ActiveRecord::SchemaMigration
|
19
|
+
.new(ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool)
|
20
|
+
.create_table
|
21
|
+
when Gem::Requirement.new("~> 7.1.0")
|
22
|
+
ActiveRecord::SchemaMigration
|
23
|
+
.new(ActiveRecord::Tasks::DatabaseTasks.migration_connection)
|
24
|
+
.create_table
|
25
|
+
when Gem::Requirement.new("< 7.1")
|
26
|
+
ActiveRecord::SchemaMigration.create_table
|
27
|
+
end
|
17
28
|
|
18
29
|
DatabaseCleaner.start
|
19
30
|
example.run
|
20
31
|
DatabaseCleaner.clean
|
21
32
|
end
|
22
33
|
|
34
|
+
config.before(:each, silence: true) do |example|
|
35
|
+
allow_any_instance_of(ActiveRecord::Migration).to receive(:say)
|
36
|
+
end
|
37
|
+
|
23
38
|
if defined? ActiveSupport::Testing::Stream
|
24
39
|
config.include ActiveSupport::Testing::Stream
|
25
40
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module DatabaseSchemaHelpers
|
2
|
+
def dump_schema(stream)
|
3
|
+
case ActiveRecord.gem_version
|
4
|
+
when Gem::Requirement.new(">= 7.2")
|
5
|
+
ActiveRecord::SchemaDumper.dump(Search.connection_pool, stream)
|
6
|
+
else
|
7
|
+
ActiveRecord::SchemaDumper.dump(Search.connection, stream)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def ar_connection
|
12
|
+
ActiveRecord::Base.connection
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_materialized_view(name, sql)
|
16
|
+
ar_connection.execute("CREATE MATERIALIZED VIEW #{name} AS #{sql}")
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_index(view, columns, name: nil)
|
20
|
+
ar_connection.add_index(view, columns, name: name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def indexes_for(view_name)
|
24
|
+
Scenic::Adapters::Postgres::Indexes
|
25
|
+
.new(connection: ar_connection)
|
26
|
+
.on(view_name)
|
27
|
+
end
|
28
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scenic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Derek Prior
|
8
8
|
- Caleb Hearth
|
9
|
-
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2025-06-30 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: bundler
|
@@ -71,16 +70,16 @@ dependencies:
|
|
71
70
|
name: pg
|
72
71
|
requirement: !ruby/object:Gem::Requirement
|
73
72
|
requirements:
|
74
|
-
- - "
|
73
|
+
- - ">="
|
75
74
|
- !ruby/object:Gem::Version
|
76
|
-
version: '0
|
75
|
+
version: '0'
|
77
76
|
type: :development
|
78
77
|
prerelease: false
|
79
78
|
version_requirements: !ruby/object:Gem::Requirement
|
80
79
|
requirements:
|
81
|
-
- - "
|
80
|
+
- - ">="
|
82
81
|
- !ruby/object:Gem::Version
|
83
|
-
version: '0
|
82
|
+
version: '0'
|
84
83
|
- !ruby/object:Gem::Dependency
|
85
84
|
name: pry
|
86
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,6 +197,7 @@ files:
|
|
198
197
|
- CHANGELOG.md
|
199
198
|
- CODE_OF_CONDUCT.md
|
200
199
|
- CONTRIBUTING.md
|
200
|
+
- FUNDING.yml
|
201
201
|
- Gemfile
|
202
202
|
- LICENSE.txt
|
203
203
|
- README.md
|
@@ -221,9 +221,13 @@ files:
|
|
221
221
|
- lib/scenic/adapters/postgres.rb
|
222
222
|
- lib/scenic/adapters/postgres/connection.rb
|
223
223
|
- lib/scenic/adapters/postgres/errors.rb
|
224
|
+
- lib/scenic/adapters/postgres/index_creation.rb
|
225
|
+
- lib/scenic/adapters/postgres/index_migration.rb
|
224
226
|
- lib/scenic/adapters/postgres/index_reapplication.rb
|
225
227
|
- lib/scenic/adapters/postgres/indexes.rb
|
226
228
|
- lib/scenic/adapters/postgres/refresh_dependencies.rb
|
229
|
+
- lib/scenic/adapters/postgres/side_by_side.rb
|
230
|
+
- lib/scenic/adapters/postgres/temporary_name.rb
|
227
231
|
- lib/scenic/adapters/postgres/views.rb
|
228
232
|
- lib/scenic/command_recorder.rb
|
229
233
|
- lib/scenic/command_recorder/statement_arguments.rb
|
@@ -258,7 +262,11 @@ files:
|
|
258
262
|
- spec/generators/scenic/view/view_generator_spec.rb
|
259
263
|
- spec/integration/revert_spec.rb
|
260
264
|
- spec/scenic/adapters/postgres/connection_spec.rb
|
265
|
+
- spec/scenic/adapters/postgres/index_creation_spec.rb
|
266
|
+
- spec/scenic/adapters/postgres/index_migration_spec.rb
|
261
267
|
- spec/scenic/adapters/postgres/refresh_dependencies_spec.rb
|
268
|
+
- spec/scenic/adapters/postgres/side_by_side_spec.rb
|
269
|
+
- spec/scenic/adapters/postgres/temporary_name_spec.rb
|
262
270
|
- spec/scenic/adapters/postgres/views_spec.rb
|
263
271
|
- spec/scenic/adapters/postgres_spec.rb
|
264
272
|
- spec/scenic/command_recorder/statement_arguments_spec.rb
|
@@ -268,14 +276,15 @@ files:
|
|
268
276
|
- spec/scenic/schema_dumper_spec.rb
|
269
277
|
- spec/scenic/statements_spec.rb
|
270
278
|
- spec/spec_helper.rb
|
279
|
+
- spec/support/database_schema_helpers.rb
|
271
280
|
- spec/support/generator_spec_setup.rb
|
272
281
|
- spec/support/rails_configuration_helpers.rb
|
273
282
|
- spec/support/view_definition_helpers.rb
|
274
283
|
homepage: https://github.com/scenic-views/scenic
|
275
284
|
licenses:
|
276
285
|
- MIT
|
277
|
-
metadata:
|
278
|
-
|
286
|
+
metadata:
|
287
|
+
funding-uri: https://github.com/scenic-views/scenic
|
279
288
|
rdoc_options: []
|
280
289
|
require_paths:
|
281
290
|
- lib
|
@@ -290,8 +299,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
290
299
|
- !ruby/object:Gem::Version
|
291
300
|
version: '0'
|
292
301
|
requirements: []
|
293
|
-
rubygems_version: 3.
|
294
|
-
signing_key:
|
302
|
+
rubygems_version: 3.6.2
|
295
303
|
specification_version: 4
|
296
304
|
summary: Support for database views in Rails migrations
|
297
305
|
test_files: []
|