spectacles 6.0.0 → 7.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/.standard.yml +4 -0
- data/CHANGELOG.md +58 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +136 -0
- data/Rakefile +15 -15
- data/lib/spectacles/abstract_adapter_override.rb +3 -3
- data/lib/spectacles/materialized_view.rb +7 -7
- data/lib/spectacles/railtie.rb +3 -3
- data/lib/spectacles/schema_dumper.rb +1 -1
- data/lib/spectacles/schema_statements/abstract_adapter.rb +15 -9
- data/lib/spectacles/schema_statements/mysql2_adapter.rb +6 -26
- data/lib/spectacles/schema_statements/postgresql_adapter.rb +31 -33
- data/lib/spectacles/schema_statements/sqlite3_adapter.rb +5 -20
- data/lib/spectacles/schema_statements/sqlserver_adapter.rb +5 -5
- data/lib/spectacles/schema_statements/vertica_adapter.rb +5 -5
- data/lib/spectacles/schema_statements.rb +2 -2
- data/lib/spectacles/version.rb +3 -1
- data/lib/spectacles/view.rb +5 -5
- data/lib/spectacles.rb +14 -12
- metadata +37 -44
- data/.gitignore +0 -8
- data/.travis.yml +0 -14
- data/Gemfile +0 -20
- data/LICENSE +0 -20
- data/Readme.rdoc +0 -120
- data/specs/adapters/mysql2_adapter_spec.rb +0 -16
- data/specs/adapters/postgresql_adapter_spec.rb +0 -68
- data/specs/adapters/sqlite3_adapter_spec.rb +0 -14
- data/specs/spec_helper.rb +0 -53
- data/specs/spectacles/abstract_adapter_override_spec.rb +0 -14
- data/specs/spectacles/schema_statements/abstract_adapter_spec.rb +0 -82
- data/specs/spectacles/view_spec.rb +0 -7
- data/specs/support/minitest_matchers.rb +0 -5
- data/specs/support/minitest_shared.rb +0 -20
- data/specs/support/schema_statement_examples.rb +0 -241
- data/specs/support/view_examples.rb +0 -62
- data/spectacles.gemspec +0 -33
@@ -1,21 +1,21 @@
|
|
1
|
-
require
|
1
|
+
require "spectacles/schema_statements/abstract_adapter"
|
2
2
|
|
3
3
|
module Spectacles
|
4
4
|
module SchemaStatements
|
5
5
|
module PostgreSQLAdapter
|
6
6
|
include Spectacles::SchemaStatements::AbstractAdapter
|
7
7
|
|
8
|
-
def views(name = nil)
|
8
|
+
def views(name = nil) # :nodoc:
|
9
9
|
q = <<-SQL
|
10
|
-
SELECT t.table_name
|
11
|
-
FROM information_schema.
|
12
|
-
INNER JOIN pg_class AS c ON c.relname = t.table_name
|
13
|
-
WHERE t.table_schema = ANY(current_schemas(
|
14
|
-
AND
|
10
|
+
SELECT t.table_name
|
11
|
+
FROM information_schema.views AS t
|
12
|
+
INNER JOIN pg_class AS c ON c.relname = t.table_name AND c.relnamespace = to_regnamespace(t.table_schema)::oid
|
13
|
+
WHERE t.table_schema = ANY(current_schemas(true))
|
14
|
+
AND table_schema NOT IN ('information_schema', 'pg_catalog')
|
15
15
|
AND pg_catalog.pg_get_userbyid(c.relowner) = #{quote(database_username)}
|
16
16
|
SQL
|
17
17
|
|
18
|
-
execute(q, name).map { |row| row[
|
18
|
+
execute(q, name).map { |row| row["table_name"] }
|
19
19
|
end
|
20
20
|
|
21
21
|
def view_build_query(view, name = nil)
|
@@ -46,7 +46,7 @@ module Spectacles
|
|
46
46
|
AND relkind = 'm';
|
47
47
|
SQL
|
48
48
|
|
49
|
-
execute(query, name).map { |row| row[
|
49
|
+
execute(query, name).map { |row| row["relname"] }
|
50
50
|
end
|
51
51
|
|
52
52
|
# Returns a tuple [string, hash], where string is the query used
|
@@ -59,8 +59,7 @@ module Spectacles
|
|
59
59
|
WHERE a.relname=#{quote(view)}
|
60
60
|
AND b.matviewname=a.relname
|
61
61
|
SQL
|
62
|
-
|
63
|
-
row = result[0]
|
62
|
+
row = result.to_a[0]
|
64
63
|
|
65
64
|
storage = row["reloptions"]
|
66
65
|
tablespace = row["tablespace"]
|
@@ -68,37 +67,37 @@ module Spectacles
|
|
68
67
|
definition = row["definition"].strip.sub(/;$/, "")
|
69
68
|
|
70
69
|
options = {}
|
71
|
-
options[:data] = false if ispopulated ==
|
70
|
+
options[:data] = false if ispopulated == "f" || ispopulated == false
|
72
71
|
options[:storage] = parse_storage_definition(storage) if storage.present?
|
73
72
|
options[:tablespace] = tablespace if tablespace.present?
|
74
73
|
|
75
74
|
[definition, options]
|
76
75
|
end
|
77
76
|
|
78
|
-
def create_materialized_view_statement(view_name, query, options={})
|
77
|
+
def create_materialized_view_statement(view_name, query, options = {})
|
79
78
|
columns = if options[:columns]
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
79
|
+
"(" + options[:columns].map { |c| quote_column_name(c) }.join(",") + ")"
|
80
|
+
else
|
81
|
+
""
|
82
|
+
end
|
84
83
|
|
85
|
-
storage = if options[:storage]
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
84
|
+
storage = if options[:storage]&.any?
|
85
|
+
"WITH (" + options[:storage].map { |key, value| "#{key}=#{value}" }.join(", ") + ")"
|
86
|
+
else
|
87
|
+
""
|
88
|
+
end
|
90
89
|
|
91
90
|
tablespace = if options[:tablespace]
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
91
|
+
"TABLESPACE #{quote_table_name(options[:tablespace])}"
|
92
|
+
else
|
93
|
+
""
|
94
|
+
end
|
96
95
|
|
97
96
|
with_data = if options.fetch(:data, true)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
97
|
+
"WITH DATA"
|
98
|
+
else
|
99
|
+
"WITH NO DATA"
|
100
|
+
end
|
102
101
|
|
103
102
|
<<-SQL.squish
|
104
103
|
CREATE MATERIALIZED VIEW #{quote_table_name(view_name)}
|
@@ -145,10 +144,9 @@ module Spectacles
|
|
145
144
|
storage = storage.first if storage.is_a?(Array)
|
146
145
|
|
147
146
|
storage = storage.gsub(/^{|}$/, "")
|
148
|
-
storage.split(
|
149
|
-
key, value = item.strip.split(
|
147
|
+
storage.split(",").each_with_object({}) do |item, hash|
|
148
|
+
key, value = item.strip.split("=")
|
150
149
|
hash[key.to_sym] = value
|
151
|
-
hash
|
152
150
|
end
|
153
151
|
end
|
154
152
|
|
@@ -1,38 +1,23 @@
|
|
1
|
-
require
|
1
|
+
require "spectacles/schema_statements/abstract_adapter"
|
2
2
|
|
3
3
|
module Spectacles
|
4
4
|
module SchemaStatements
|
5
5
|
module SQLite3Adapter
|
6
6
|
include Spectacles::SchemaStatements::AbstractAdapter
|
7
7
|
|
8
|
-
# overrides the #tables method from ActiveRecord's SQLite3Adapter
|
9
|
-
# to return only tables, and not views.
|
10
|
-
def tables(name = nil, table_name = nil)
|
11
|
-
sql = <<-SQL
|
12
|
-
SELECT name
|
13
|
-
FROM sqlite_master
|
14
|
-
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
15
|
-
SQL
|
16
|
-
sql << " AND name = #{quote_table_name(table_name)}" if table_name
|
17
|
-
|
18
|
-
exec_query(sql, 'SCHEMA').map do |row|
|
19
|
-
row['name']
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
8
|
def generate_view_query(*columns)
|
24
9
|
<<-SQL
|
25
|
-
SELECT #{columns.join(
|
10
|
+
SELECT #{columns.join(",")}
|
26
11
|
FROM sqlite_master
|
27
12
|
WHERE type = 'view'
|
28
13
|
SQL
|
29
14
|
end
|
30
15
|
|
31
|
-
def views
|
16
|
+
def views # :nodoc:
|
32
17
|
sql = generate_view_query(:name)
|
33
18
|
|
34
19
|
exec_query(sql, "SCHEMA").map do |row|
|
35
|
-
row[
|
20
|
+
row["name"]
|
36
21
|
end
|
37
22
|
end
|
38
23
|
|
@@ -41,7 +26,7 @@ module Spectacles
|
|
41
26
|
sql << " AND name = #{quote_table_name(table_name)}"
|
42
27
|
|
43
28
|
row = exec_query(sql, "SCHEMA").first
|
44
|
-
row[
|
29
|
+
row["sql"].gsub(/CREATE VIEW .*? AS/i, "")
|
45
30
|
end
|
46
31
|
end
|
47
32
|
end
|
@@ -1,22 +1,22 @@
|
|
1
|
-
require
|
1
|
+
require "spectacles/schema_statements/abstract_adapter"
|
2
2
|
|
3
3
|
module Spectacles
|
4
4
|
module SchemaStatements
|
5
5
|
module SQLServerAdapter
|
6
6
|
include Spectacles::SchemaStatements::AbstractAdapter
|
7
|
-
|
8
|
-
def views(name = nil)
|
7
|
+
|
8
|
+
def views(name = nil) # :nodoc:
|
9
9
|
select_values("SELECT table_name FROM information_schema.views", name)
|
10
10
|
end
|
11
11
|
|
12
12
|
def view_build_query(view, name = nil)
|
13
|
-
q
|
13
|
+
q = <<-ENDSQL
|
14
14
|
SELECT view_definition FROM information_schema.views
|
15
15
|
WHERE table_name = '#{view}'
|
16
16
|
ENDSQL
|
17
17
|
|
18
18
|
q = select_value(q, name) or raise "No view called #{view} found"
|
19
|
-
q.gsub(/CREATE VIEW .*? AS/i, "")
|
19
|
+
q.gsub(/CREATE VIEW .*? AS/i, "")
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -1,23 +1,23 @@
|
|
1
|
-
require
|
1
|
+
require "spectacles/schema_statements/abstract_adapter"
|
2
2
|
|
3
3
|
module Spectacles
|
4
4
|
module SchemaStatements
|
5
5
|
module VerticaAdapter
|
6
6
|
include Spectacles::SchemaStatements::AbstractAdapter
|
7
|
-
|
7
|
+
|
8
8
|
def views(name = nil)
|
9
9
|
q = <<-SQL
|
10
10
|
SELECT table_name FROM v_catalog.views
|
11
11
|
SQL
|
12
|
-
|
13
|
-
execute(q, name).map { |row| row[
|
12
|
+
|
13
|
+
execute(q, name).map { |row| row["table_name"] }
|
14
14
|
end
|
15
15
|
|
16
16
|
def view_build_query(view, name = nil)
|
17
17
|
q = <<-SQL
|
18
18
|
SELECT view_definition FROM v_catalog.views WHERE table_name = '#{view}'
|
19
19
|
SQL
|
20
|
-
|
20
|
+
|
21
21
|
select_value(q, name) or raise "No view called #{view} found"
|
22
22
|
end
|
23
23
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
1
|
+
require "spectacles/schema_statements/abstract_adapter"
|
2
2
|
|
3
3
|
module Spectacles
|
4
|
-
SUPPORTED_ADAPTERS = %w
|
4
|
+
SUPPORTED_ADAPTERS = %w[Mysql2 PostgreSQL SQLServer SQLite SQLite3 Vertica]
|
5
5
|
|
6
6
|
def self.load_adapters
|
7
7
|
SUPPORTED_ADAPTERS.each do |db|
|
data/lib/spectacles/version.rb
CHANGED
data/lib/spectacles/view.rb
CHANGED
@@ -7,7 +7,7 @@ module Spectacles
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.view_exists?
|
10
|
-
|
10
|
+
connection.view_exists?(view_name)
|
11
11
|
end
|
12
12
|
|
13
13
|
class << self
|
@@ -15,11 +15,11 @@ module Spectacles
|
|
15
15
|
alias_method :view_name, :table_name
|
16
16
|
end
|
17
17
|
|
18
|
-
def ==(
|
18
|
+
def ==(other)
|
19
19
|
super ||
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
other.instance_of?(self.class) &&
|
21
|
+
attributes.present? &&
|
22
|
+
other.attributes == attributes
|
23
23
|
end
|
24
24
|
|
25
25
|
def persisted?
|
data/lib/spectacles.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
|
11
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record"
|
4
|
+
require "active_support/core_ext"
|
5
|
+
require "spectacles/schema_statements"
|
6
|
+
require "spectacles/schema_dumper"
|
7
|
+
require "spectacles/view"
|
8
|
+
require "spectacles/materialized_view"
|
9
|
+
require "spectacles/version"
|
10
|
+
require "spectacles/configuration"
|
11
|
+
require "spectacles/abstract_adapter_override"
|
12
|
+
|
13
|
+
require "spectacles/railtie" if defined?(Rails)
|
12
14
|
|
13
15
|
module Spectacles
|
14
16
|
def self.configuration
|
@@ -34,4 +36,4 @@ ActiveRecord::SchemaDumper.class_eval do
|
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
37
|
-
Spectacles
|
39
|
+
Spectacles.load_adapters
|
metadata
CHANGED
@@ -1,55 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spectacles
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 7.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Hutchison, Brandon Dewitt
|
8
|
-
autorequire:
|
9
|
-
bindir:
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 3.2.0
|
20
17
|
- - "~>"
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
19
|
+
version: 7.1.0
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 3.2.0
|
30
24
|
- - "~>"
|
31
25
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
26
|
+
version: 7.1.0
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: activesupport
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
|
-
- - ">="
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: 3.2.0
|
40
31
|
- - "~>"
|
41
32
|
- !ruby/object:Gem::Version
|
42
|
-
version:
|
33
|
+
version: 7.1.0
|
43
34
|
type: :runtime
|
44
35
|
prerelease: false
|
45
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 7.1.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
46
44
|
requirements:
|
47
45
|
- - ">="
|
48
46
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
50
|
-
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
51
53
|
- !ruby/object:Gem::Version
|
52
|
-
version:
|
54
|
+
version: '5.0'
|
53
55
|
- !ruby/object:Gem::Dependency
|
54
56
|
name: rake
|
55
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -65,7 +67,7 @@ dependencies:
|
|
65
67
|
- !ruby/object:Gem::Version
|
66
68
|
version: '0'
|
67
69
|
- !ruby/object:Gem::Dependency
|
68
|
-
name:
|
70
|
+
name: standard
|
69
71
|
requirement: !ruby/object:Gem::Requirement
|
70
72
|
requirements:
|
71
73
|
- - ">="
|
@@ -86,12 +88,13 @@ executables: []
|
|
86
88
|
extensions: []
|
87
89
|
extra_rdoc_files: []
|
88
90
|
files:
|
89
|
-
- ".
|
90
|
-
- ".
|
91
|
-
-
|
92
|
-
-
|
91
|
+
- ".rubocop.yml"
|
92
|
+
- ".standard.yml"
|
93
|
+
- CHANGELOG.md
|
94
|
+
- CODE_OF_CONDUCT.md
|
95
|
+
- LICENSE.txt
|
96
|
+
- README.md
|
93
97
|
- Rakefile
|
94
|
-
- Readme.rdoc
|
95
98
|
- lib/spectacles.rb
|
96
99
|
- lib/spectacles/abstract_adapter_override.rb
|
97
100
|
- lib/spectacles/configuration.rb
|
@@ -107,23 +110,14 @@ files:
|
|
107
110
|
- lib/spectacles/schema_statements/vertica_adapter.rb
|
108
111
|
- lib/spectacles/version.rb
|
109
112
|
- lib/spectacles/view.rb
|
110
|
-
- specs/adapters/mysql2_adapter_spec.rb
|
111
|
-
- specs/adapters/postgresql_adapter_spec.rb
|
112
|
-
- specs/adapters/sqlite3_adapter_spec.rb
|
113
|
-
- specs/spec_helper.rb
|
114
|
-
- specs/spectacles/abstract_adapter_override_spec.rb
|
115
|
-
- specs/spectacles/schema_statements/abstract_adapter_spec.rb
|
116
|
-
- specs/spectacles/view_spec.rb
|
117
|
-
- specs/support/minitest_matchers.rb
|
118
|
-
- specs/support/minitest_shared.rb
|
119
|
-
- specs/support/schema_statement_examples.rb
|
120
|
-
- specs/support/view_examples.rb
|
121
|
-
- spectacles.gemspec
|
122
113
|
homepage: http://github.com/liveh2o/spectacles
|
123
114
|
licenses:
|
124
115
|
- MIT
|
125
|
-
metadata:
|
126
|
-
|
116
|
+
metadata:
|
117
|
+
homepage_uri: http://github.com/liveh2o/spectacles
|
118
|
+
source_code_uri: http://github.com/liveh2o/spectacles
|
119
|
+
changelog_uri: http://github.com/liveh2o/spectacles/blob/main/CHANGELOG.md
|
120
|
+
post_install_message:
|
127
121
|
rdoc_options: []
|
128
122
|
require_paths:
|
129
123
|
- lib
|
@@ -131,16 +125,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
131
125
|
requirements:
|
132
126
|
- - ">="
|
133
127
|
- !ruby/object:Gem::Version
|
134
|
-
version: 2.
|
128
|
+
version: 2.7.0
|
135
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
130
|
requirements:
|
137
131
|
- - ">="
|
138
132
|
- !ruby/object:Gem::Version
|
139
133
|
version: '0'
|
140
134
|
requirements: []
|
141
|
-
rubygems_version: 3.
|
142
|
-
signing_key:
|
135
|
+
rubygems_version: 3.4.22
|
136
|
+
signing_key:
|
143
137
|
specification_version: 4
|
144
|
-
summary: Spectacles
|
145
|
-
to ActiveRecord.
|
138
|
+
summary: Spectacles adds database view functionality to ActiveRecord.
|
146
139
|
test_files: []
|
data/.gitignore
DELETED
data/.travis.yml
DELETED
data/Gemfile
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
source "http://rubygems.org"
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in spectacles.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
platforms :jruby do
|
7
|
-
gem "activerecord-jdbcmysql-adapter"
|
8
|
-
gem "activerecord-jdbcpostgresql-adapter"
|
9
|
-
gem "activerecord-jdbcsqlite3-adapter"
|
10
|
-
end
|
11
|
-
|
12
|
-
platforms :ruby do
|
13
|
-
gem "mysql2"
|
14
|
-
gem "pg"
|
15
|
-
gem "sqlite3"
|
16
|
-
end
|
17
|
-
|
18
|
-
group :test do
|
19
|
-
gem 'simplecov', :require => false
|
20
|
-
end
|
data/LICENSE
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2012-2019 Adam Hutchison, Brandon Dewitt
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
-
this software and associated documentation files (the "Software"), to deal in
|
7
|
-
the Software without restriction, including without limitation the rights to
|
8
|
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
-
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
-
subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
13
|
-
copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Readme.rdoc
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
{<img src="https://travis-ci.org/liveh2o/spectacles.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/liveh2o/spectacles] {<img src="https://badge.fury.io/rb/spectacles.svg" alt="Gem Version" />}[https://badge.fury.io/rb/spectacles]
|
2
|
-
|
3
|
-
= Spectacles
|
4
|
-
|
5
|
-
Spectacles adds database view functionality to ActiveRecord. It is heavily inspired by Rails SQL Views (created by https://github.com/aeden but no longer maintained) and built from the ground up to work with Rails 3.2+.
|
6
|
-
|
7
|
-
Spectacles provides the ability to create views in migrations using a similar format to creating tables. It also provides an abstract view class that inherits from ActiveRecord::Base that can be used to create view-backed models.
|
8
|
-
|
9
|
-
It currently works with the SQLite, MySQL, MySQL2, PostgreSQL, and Vertica drivers.
|
10
|
-
|
11
|
-
= Using Spectacles
|
12
|
-
Install it
|
13
|
-
gem install spectacles # => OR include it in your Gemfile
|
14
|
-
|
15
|
-
== Migrations
|
16
|
-
|
17
|
-
Create a migration from an query string:
|
18
|
-
|
19
|
-
create_view :product_users do
|
20
|
-
"SELECT name AS product_name, first_name AS username FROM
|
21
|
-
products JOIN users ON users.id = products.user_id"
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
Create a migration from an ARel object:
|
26
|
-
|
27
|
-
create_view :product_users do
|
28
|
-
Product.select("products.name AS product_name).
|
29
|
-
select("users.first_name AS username").
|
30
|
-
join(:users)
|
31
|
-
end
|
32
|
-
|
33
|
-
== Models
|
34
|
-
|
35
|
-
class ProductUser < Spectacles::View
|
36
|
-
# Add relationships
|
37
|
-
|
38
|
-
# Use scopes
|
39
|
-
|
40
|
-
# Your fancy methods
|
41
|
-
end
|
42
|
-
|
43
|
-
== Materialized Views
|
44
|
-
|
45
|
-
*This feature is only supported for PostgreSQL backends.*
|
46
|
-
These are essentially views that cache their result set. In this way
|
47
|
-
they are kind of a cross between tables (which persist data) and views
|
48
|
-
(which are windows onto other tables).
|
49
|
-
|
50
|
-
create_materialized_view :product_users do
|
51
|
-
<<-SQL.squish
|
52
|
-
SELECT name AS product_name, first_name AS username
|
53
|
-
FROM products
|
54
|
-
JOIN users ON users.id = products.user_id
|
55
|
-
SQL
|
56
|
-
end
|
57
|
-
|
58
|
-
class ProductUser < Spectacles::MaterializedView
|
59
|
-
# just like Spectacles::View
|
60
|
-
end
|
61
|
-
|
62
|
-
Because materialized views cache a snapshot of the data as it
|
63
|
-
exists at a point in time (typically when the view was created), you
|
64
|
-
need to manually _refresh_ the view when new data is added to the
|
65
|
-
original tables. You can do this with the +#refresh!+ method on
|
66
|
-
the +Spectacles::MaterializedView+ subclass:
|
67
|
-
|
68
|
-
User.create(first_name: "Bob", email: "bob@example.com")
|
69
|
-
ProductUser.refresh!
|
70
|
-
|
71
|
-
Also, you can specify a few different options to +create_materialized_view+
|
72
|
-
to affect how the new view is created:
|
73
|
-
|
74
|
-
* +:force+ - if +false+ (the default), the create will fail if a
|
75
|
-
materialized view with the given name already exists. If +true+,
|
76
|
-
any materialized view with that name will be dropped before the
|
77
|
-
create runs.
|
78
|
-
|
79
|
-
create_materialized_view :product_users, force: true do
|
80
|
-
# ...
|
81
|
-
end
|
82
|
-
|
83
|
-
* +:data+ - if +true+ (the default), the view is immediately populated
|
84
|
-
with the corresponding data. If +false+, the view will be empty initially,
|
85
|
-
and must be populated by invoking the +#refresh!+ method.
|
86
|
-
|
87
|
-
create_materialized_view :product_users, data: false do
|
88
|
-
# ...
|
89
|
-
end
|
90
|
-
|
91
|
-
* +:columns+ - an optional array of names to give the columns in the view.
|
92
|
-
By default, columns in the view will use the names given in the query.
|
93
|
-
|
94
|
-
create_materialized_view :product_users, columns: %i(product_name username) do
|
95
|
-
<<-SQL.squish
|
96
|
-
SELECT products.name, users.first_name
|
97
|
-
FROM products
|
98
|
-
JOIN users ON users.id = products.user_id
|
99
|
-
SQL
|
100
|
-
end
|
101
|
-
|
102
|
-
* +:tablespace+ - an optional identifier (string or symbol) indicating
|
103
|
-
which namespace the materialized view ought to be created in.
|
104
|
-
|
105
|
-
create_materialized_view :product_users, tablespace: "awesomesauce" do
|
106
|
-
# ...
|
107
|
-
end
|
108
|
-
|
109
|
-
* +:storage+ - an optional hash of (database-specific) storage parameters to
|
110
|
-
optimize how the materialized view is stored. (See
|
111
|
-
http://www.postgresql.org/docs/9.4/static/sql-createtable.html#SQL-CREATETABLE-STORAGE-PARAMETERS
|
112
|
-
for details.)
|
113
|
-
|
114
|
-
create_materialized_view :product_users, storage: { fillfactor: 70 } do
|
115
|
-
# ...
|
116
|
-
end
|
117
|
-
|
118
|
-
= License
|
119
|
-
|
120
|
-
Spectacles is licensed under MIT license (Read the LICENSE file for full license)
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "Spectacles::SchemaStatements::Mysql2Adapter" do
|
4
|
-
config = {
|
5
|
-
:adapter => "mysql2",
|
6
|
-
:host => "localhost",
|
7
|
-
:username => "root"
|
8
|
-
}
|
9
|
-
|
10
|
-
configure_database(config)
|
11
|
-
recreate_database("spectacles_test")
|
12
|
-
load_schema
|
13
|
-
|
14
|
-
it_behaves_like "an adapter", "Mysql2Adapter"
|
15
|
-
it_behaves_like "a view model"
|
16
|
-
end
|