spectacles 2.0.0 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/.standard.yml +4 -0
  4. data/CHANGELOG.md +54 -0
  5. data/CODE_OF_CONDUCT.md +132 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +136 -0
  8. data/Rakefile +15 -15
  9. data/lib/spectacles/abstract_adapter_override.rb +3 -3
  10. data/lib/spectacles/materialized_view.rb +7 -7
  11. data/lib/spectacles/railtie.rb +3 -3
  12. data/lib/spectacles/schema_dumper.rb +1 -1
  13. data/lib/spectacles/schema_statements/abstract_adapter.rb +15 -9
  14. data/lib/spectacles/schema_statements/mysql2_adapter.rb +3 -3
  15. data/lib/spectacles/schema_statements/postgresql_adapter.rb +31 -33
  16. data/lib/spectacles/schema_statements/sqlite3_adapter.rb +7 -7
  17. data/lib/spectacles/schema_statements/sqlserver_adapter.rb +5 -5
  18. data/lib/spectacles/schema_statements/vertica_adapter.rb +5 -5
  19. data/lib/spectacles/schema_statements.rb +2 -2
  20. data/lib/spectacles/version.rb +3 -1
  21. data/lib/spectacles/view.rb +5 -5
  22. data/lib/spectacles.rb +14 -12
  23. metadata +37 -44
  24. data/.gitignore +0 -8
  25. data/.travis.yml +0 -14
  26. data/Gemfile +0 -20
  27. data/LICENSE +0 -20
  28. data/Readme.rdoc +0 -120
  29. data/specs/adapters/mysql2_adapter_spec.rb +0 -16
  30. data/specs/adapters/postgresql_adapter_spec.rb +0 -68
  31. data/specs/adapters/sqlite3_adapter_spec.rb +0 -14
  32. data/specs/spec_helper.rb +0 -53
  33. data/specs/spectacles/abstract_adapter_override_spec.rb +0 -14
  34. data/specs/spectacles/schema_statements/abstract_adapter_spec.rb +0 -82
  35. data/specs/spectacles/view_spec.rb +0 -7
  36. data/specs/support/minitest_matchers.rb +0 -5
  37. data/specs/support/minitest_shared.rb +0 -20
  38. data/specs/support/schema_statement_examples.rb +0 -241
  39. data/specs/support/view_examples.rb +0 -62
  40. data/spectacles.gemspec +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c759a317da5654cfbfb8aadbabe40a10122b75fa2cd0a569b9d7cb6792b490a
4
- data.tar.gz: a76b8d1e07255df03cfed644e868cc7bd4f153ce189e8e457fd2e155f09b5398
3
+ metadata.gz: 3828ebda72819be07a7e380017782c6ce623c556b7a55a66b0817c8274bc5699
4
+ data.tar.gz: c8202a385e3fef197c8db980ee53f0f104c3310608a46c60cb5756aa2526ed9c
5
5
  SHA512:
6
- metadata.gz: 25f113ee6cfc34e1989378d3710c899a340271a37879be95aea22817fbb86ad09c14fb978c90b20a0dd5476f895739fdc902d97b6b5a288a9ae012291736b2dd
7
- data.tar.gz: d372e0d4dae6f83b2396f582012de107a39cdfd0d57acfb77974aa9d5b9297972eb111b6eb07862c0d34241075392daddc6ef3fdd47224b8b2b9f85035a5723a
6
+ metadata.gz: 0204f98f169707aee585e76e7b3f61fff5639e42bb3b7655e0a2c2c0c54a4dea2891c8edcd5c85a498f1dce4c4e169c0ab9793c145f7be4e2960e90973307550
7
+ data.tar.gz: a8f20c62cca8e1c8868d12522f9e37ac5826fd9e1f5b25357929be2f256a020f913a227563f81d0203ec3e2b866c61639a255dde24fd450f8d3a3e7b864b5d48
data/.rubocop.yml ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ inherit_gem:
3
+ standard: config/ruby-2.7.yml
data/.standard.yml ADDED
@@ -0,0 +1,4 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/standardrb/standard
3
+ ruby_version: 2.7 # default: RUBY_VERSION
4
+ format: progress # default: Standard::Formatter
data/CHANGELOG.md ADDED
@@ -0,0 +1,54 @@
1
+ All notable changes to this project will be documented in this file.
2
+
3
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [7.0.0] – 2024-11-26
9
+
10
+ - Add support for dumping views from multiple schemas in Postgres ([#32](https://github.com/liveh2o/spectacles/pull/32))
11
+ - Require Ruby 2.7+
12
+ - Require Rails 7.0
13
+
14
+ ## [6.0.0] – 2022-02-21
15
+
16
+ - Add Rails 6.0 support
17
+
18
+ ## [2.0.0] – 2019-12-17
19
+
20
+ - Add support for materialized views
21
+ - Drop support for the the mysql gem
22
+ - Require Ruby 2.2+
23
+
24
+ ## [1.2.0] – 2017-07-21
25
+
26
+ - Add support for skipping views when dumping the schema
27
+
28
+ ## [1.1.0] – 2016-01-15
29
+
30
+ ## [1.0.1] – 2015-09-29
31
+
32
+ ## [1.0.0] – 2015-09-28
33
+
34
+ ## [0.5.3] – 2015-03-16
35
+
36
+ ## [0.5.2] – 2014-12-05
37
+
38
+ ## [0.5.1] – 2014-02-07
39
+
40
+ ## [0.5.0] – 2014-01-03
41
+
42
+ ## [0.4.1] – 2013-11-14
43
+
44
+ ## [0.4.0] – 2013-10-10
45
+
46
+ ## [0.3.1] – 2013-10-04
47
+
48
+ ## [0.3.0] – 2013-09-27
49
+
50
+ ## [0.2.0] – 2013-04-22
51
+
52
+ ## [0.1.0] – 2013-01-14
53
+
54
+ ## [0.0.2] – 2012-02-10
@@ -0,0 +1,132 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the overall
26
+ community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or advances of
31
+ any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email address,
35
+ without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official email address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ [INSERT CONTACT METHOD].
64
+ All complaints will be reviewed and investigated promptly and fairly.
65
+
66
+ All community leaders are obligated to respect the privacy and security of the
67
+ reporter of any incident.
68
+
69
+ ## Enforcement Guidelines
70
+
71
+ Community leaders will follow these Community Impact Guidelines in determining
72
+ the consequences for any action they deem in violation of this Code of Conduct:
73
+
74
+ ### 1. Correction
75
+
76
+ **Community Impact**: Use of inappropriate language or other behavior deemed
77
+ unprofessional or unwelcome in the community.
78
+
79
+ **Consequence**: A private, written warning from community leaders, providing
80
+ clarity around the nature of the violation and an explanation of why the
81
+ behavior was inappropriate. A public apology may be requested.
82
+
83
+ ### 2. Warning
84
+
85
+ **Community Impact**: A violation through a single incident or series of
86
+ actions.
87
+
88
+ **Consequence**: A warning with consequences for continued behavior. No
89
+ interaction with the people involved, including unsolicited interaction with
90
+ those enforcing the Code of Conduct, for a specified period of time. This
91
+ includes avoiding interactions in community spaces as well as external channels
92
+ like social media. Violating these terms may lead to a temporary or permanent
93
+ ban.
94
+
95
+ ### 3. Temporary Ban
96
+
97
+ **Community Impact**: A serious violation of community standards, including
98
+ sustained inappropriate behavior.
99
+
100
+ **Consequence**: A temporary ban from any sort of interaction or public
101
+ communication with the community for a specified period of time. No public or
102
+ private interaction with the people involved, including unsolicited interaction
103
+ with those enforcing the Code of Conduct, is allowed during this period.
104
+ Violating these terms may lead to a permanent ban.
105
+
106
+ ### 4. Permanent Ban
107
+
108
+ **Community Impact**: Demonstrating a pattern of violation of community
109
+ standards, including sustained inappropriate behavior, harassment of an
110
+ individual, or aggression toward or disparagement of classes of individuals.
111
+
112
+ **Consequence**: A permanent ban from any sort of public interaction within the
113
+ community.
114
+
115
+ ## Attribution
116
+
117
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
+ version 2.1, available at
119
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120
+
121
+ Community Impact Guidelines were inspired by
122
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123
+
124
+ For answers to common questions about this code of conduct, see the FAQ at
125
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126
+ [https://www.contributor-covenant.org/translations][translations].
127
+
128
+ [homepage]: https://www.contributor-covenant.org
129
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130
+ [Mozilla CoC]: https://github.com/mozilla/diversity
131
+ [FAQ]: https://www.contributor-covenant.org/faq
132
+ [translations]: https://www.contributor-covenant.org/translations
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2012-2024 Adam Hutchison, Brandon Dewitt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all 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,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,136 @@
1
+ [![CI](https://github.com/liveh2o/spectacles/actions/workflows/main.yml/badge.svg)](https://github.com/liveh2o/spectacles/actions)
2
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/standardrb/standard)
3
+ [![Gem Version](https://badge.fury.io/rb/spectacles.svg)](https://badge.fury.io/rb/spectacles)
4
+
5
+ # Spectacles
6
+
7
+ 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.
8
+
9
+ 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.
10
+
11
+ It currently works with the SQLite, MySQL2, PostgreSQL, and Vertica drivers.
12
+
13
+ # Using Spectacles
14
+
15
+ Install it
16
+
17
+ ```shell
18
+ $ gem install spectacles # => OR include it in your Gemfile
19
+ ```
20
+
21
+ ## Migrations
22
+
23
+ Create a migration from an query string:
24
+
25
+ ```ruby
26
+ create_view :product_users do
27
+ "SELECT name AS product_name, first_name AS username FROM products JOIN users ON users.id = products.user_id"
28
+ end
29
+ ```
30
+
31
+ Create a migration from an ARel object:
32
+
33
+ ```ruby
34
+ create_view :product_users do
35
+ Product.select("products.name AS product_name).select("users.first_name AS username").join(:users)
36
+ end
37
+ ```
38
+
39
+ ## Models
40
+
41
+ ```ruby
42
+ class ProductUser < Spectacles::View # Add relationships
43
+ # Use scopes
44
+
45
+ # Your fancy methods
46
+ end
47
+ ```
48
+
49
+ ## Materialized Views
50
+
51
+ _This feature is only supported for PostgreSQL backends._
52
+
53
+ These are essentially views that cache their result set. In this way they are kind of a cross between tables (which persist data) and views
54
+ (which are windows onto other tables).
55
+
56
+ ```ruby
57
+ create_materialized_view :product_users do
58
+ <<-SQL.squish
59
+ SELECT name AS product_name, first_name AS username
60
+ FROM products
61
+ JOIN users ON users.id = products.user_id
62
+ SQL
63
+ end
64
+
65
+ class ProductUser < Spectacles::MaterializedView # just like Spectacles::View
66
+ end
67
+ ```
68
+
69
+ Because materialized views cache a snapshot of the data as it exists at a point in time (typically when the view was created), you
70
+ need to manually _refresh_ the view when new data is added to the original tables. You can do this with the `#refresh!` method on
71
+ the `Spectacles::MaterializedView` subclass:
72
+
73
+ ```ruby
74
+ User.create(first_name: "Bob", email: "bob@example.com")
75
+ ProductUser.refresh!
76
+ ```
77
+
78
+ Also, you can specify a few different options to `create_materialized_view` to affect how the new view is created:
79
+
80
+ - `:force` - if `false` (the default), the create will fail if a
81
+ materialized view with the given name already exists. If `true`,
82
+ any materialized view with that name will be dropped before the
83
+ create runs.
84
+
85
+ ```ruby
86
+ create_materialized_view :product_users, force: true do
87
+ # ...
88
+ end
89
+ ```
90
+
91
+ - `:data` - if `true` (the default), the view is immediately populated
92
+ with the corresponding data. If `false`, the view will be empty initially,
93
+ and must be populated by invoking the `#refresh!` method.
94
+
95
+ ```ruby
96
+ create_materialized_view :product_users, data: false do
97
+ # ...
98
+ end
99
+ ```
100
+
101
+ - `:columns` - an optional array of names to give the columns in the view.
102
+ By default, columns in the view will use the names given in the query.
103
+
104
+ ```ruby
105
+ create_materialized_view :product_users, columns: %i(product_name username) do
106
+ <<-SQL.squish
107
+ SELECT products.name, users.first_name
108
+ FROM products
109
+ JOIN users ON users.id = products.user_id
110
+ SQL
111
+ end
112
+ ```
113
+
114
+ - `:tablespace` - an optional identifier (string or symbol) indicating
115
+ which namespace the materialized view ought to be created in.
116
+
117
+ ```ruby
118
+ create_materialized_view :product_users, tablespace: "awesomesauce" do
119
+ # ...
120
+ end
121
+ ```
122
+
123
+ - `:storage` - an optional hash of (database-specific) storage parameters to
124
+ optimize how the materialized view is stored. (See
125
+ http://www.postgresql.org/docs/9.4/static/sql-createtable.html#SQL-CREATETABLE-STORAGE-PARAMETERS
126
+ for details.)
127
+
128
+ ```ruby
129
+ create_materialized_view :product_users, storage: { fillfactor: 70 } do
130
+ # ...
131
+ end
132
+ ```
133
+
134
+ # License
135
+
136
+ Spectacles is licensed under MIT license (Read the LICENSE file for full license)
data/Rakefile CHANGED
@@ -1,25 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
- require 'rake/testtask'
4
+ require "minitest/test_task"
3
5
 
4
6
  namespace :test do
5
- adapters = [ :mysql2, :postgresql, :sqlite3 ]
6
- task :all => [ :spectacles ] + adapters
7
+ Minitest::TestTask.create :spectacles do |t|
8
+ t.test_globs = ["test/spectacles/**/*_test.rb"]
9
+ t.warning = false
10
+ end
7
11
 
12
+ adapters = %i[mysql2 postgresql sqlite3]
8
13
  adapters.each do |adapter|
9
- Rake::TestTask.new(adapter) do |t|
10
- t.libs.push "lib"
11
- t.libs.push "specs"
12
- t.pattern = "specs/adapters/#{t.name}*_spec.rb"
13
- t.verbose = true
14
+ Minitest::TestTask.create adapter do |t|
15
+ t.test_globs = ["test/adapters/#{t.name}*_test.rb"]
16
+ t.warning = false
14
17
  end
15
18
  end
16
19
 
17
- Rake::TestTask.new(:spectacles) do |t|
18
- t.libs.push "lib"
19
- t.libs.push "specs"
20
- t.pattern = "specs/spectacles/**/*_spec.rb"
21
- t.verbose = true
22
- end
20
+ task all: %i[spectacles] + adapters
23
21
  end
24
22
 
25
- task :default => 'test:all'
23
+ require "standard/rake"
24
+
25
+ task default: %i[test:all standard:fix]
@@ -2,9 +2,9 @@ ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
2
2
  class << self
3
3
  alias_method(:_spectacles_orig_inherited, :inherited) if method_defined?(:inherited)
4
4
 
5
- def inherited(_subclass)
6
- ::Spectacles::load_adapters
7
- _spectacles_orig_inherited(_subclass) if methods.include?(:_spectacles_orig_inherited)
5
+ def inherited(klass)
6
+ ::Spectacles.load_adapters
7
+ _spectacles_orig_inherited(klass) if methods.include?(:_spectacles_orig_inherited)
8
8
  end
9
9
  end
10
10
  end
@@ -7,14 +7,14 @@ module Spectacles
7
7
  end
8
8
 
9
9
  def self.materialized_view_exists?
10
- self.connection.materialized_view_exists?(self.view_name)
10
+ connection.materialized_view_exists?(view_name)
11
11
  end
12
12
 
13
13
  def self.refresh!(concurrently: false)
14
14
  if concurrently
15
- self.connection.refresh_materialized_view_concurrently(self.view_name)
15
+ connection.refresh_materialized_view_concurrently(view_name)
16
16
  else
17
- self.connection.refresh_materialized_view(self.view_name)
17
+ connection.refresh_materialized_view(view_name)
18
18
  end
19
19
  end
20
20
 
@@ -27,11 +27,11 @@ module Spectacles
27
27
  alias_method :view_name, :table_name
28
28
  end
29
29
 
30
- def ==(comparison_object)
30
+ def ==(other)
31
31
  super ||
32
- comparison_object.instance_of?(self.class) &&
33
- attributes.present? &&
34
- comparison_object.attributes == attributes
32
+ other.instance_of?(self.class) &&
33
+ attributes.present? &&
34
+ other.attributes == attributes
35
35
  end
36
36
 
37
37
  def persisted?
@@ -1,11 +1,11 @@
1
- require 'spectacles'
2
- require 'rails'
1
+ require "spectacles"
2
+ require "rails"
3
3
 
4
4
  module Spectacles
5
5
  class Railtie < ::Rails::Railtie
6
6
  config.spectacles = ::ActiveSupport::OrderedOptions.new
7
7
 
8
- initializer 'spectacles.configure' do |app|
8
+ initializer "spectacles.configure" do |app|
9
9
  Spectacles.configure do |config|
10
10
  if app.config.spectacles.key?(:enable_schema_dump)
11
11
  config.enable_schema_dump = app.config.spectacles[:enable_schema_dump]
@@ -48,7 +48,7 @@ module Spectacles
48
48
  def self.format_option_hash(hash)
49
49
  hash.map do |key, value|
50
50
  "#{key}: #{format_option_value(value)}"
51
- end.join(', ')
51
+ end.join(", ")
52
52
  end
53
53
 
54
54
  def self.format_option_value(value)
@@ -15,14 +15,20 @@ module Spectacles
15
15
  end
16
16
 
17
17
  query = create_view_statement(view_name, build_query)
18
- execute(query)
18
+ if defined?(ActiveRecord::Base.connection_handler) && ActiveRecord.respond_to?(:legacy_connection_handling) && ActiveRecord.legacy_connection_handling
19
+ ActiveRecord::Base.connection_handler.while_preventing_writes(false) do
20
+ execute(query)
21
+ end
22
+ else
23
+ execute(query)
24
+ end
19
25
  end
20
26
 
21
27
  def create_view_statement(view_name, create_query)
22
- #query = "CREATE VIEW ? AS #{create_query}"
23
- #query_array = [query, view_name.to_s]
28
+ # query = "CREATE VIEW ? AS #{create_query}"
29
+ # query_array = [query, view_name.to_s]
24
30
 
25
- #return ActiveRecord::Base.__send__(:sanitize_sql_array, query_array)
31
+ # return ActiveRecord::Base.__send__(:sanitize_sql_array, query_array)
26
32
  "CREATE VIEW #{view_name} AS #{create_query}"
27
33
  end
28
34
 
@@ -32,15 +38,15 @@ module Spectacles
32
38
  end
33
39
 
34
40
  def drop_view_statement(view_name)
35
- #query = "DROP VIEW IF EXISTS ? "
36
- #query_array = [query, view_name.to_s]
41
+ # query = "DROP VIEW IF EXISTS ? "
42
+ # query_array = [query, view_name.to_s]
37
43
 
38
- #return ActiveRecord::Base.__send__(:sanitize_sql_array, query_array)
44
+ # return ActiveRecord::Base.__send__(:sanitize_sql_array, query_array)
39
45
  "DROP VIEW IF EXISTS #{view_name} "
40
46
  end
41
47
 
42
48
  def view_exists?(name)
43
- return views.include?(name.to_s)
49
+ views.include?(name.to_s)
44
50
  end
45
51
 
46
52
  def views
@@ -52,7 +58,7 @@ module Spectacles
52
58
  end
53
59
 
54
60
  def materialized_view_exists?(name)
55
- return materialized_views.include?(name.to_s)
61
+ materialized_views.include?(name.to_s)
56
62
  end
57
63
 
58
64
  def materialized_views
@@ -17,12 +17,12 @@ module Spectacles
17
17
  #{by_name}
18
18
  SQL
19
19
 
20
- execute_and_free(sql, 'SCHEMA') do |result|
20
+ execute_and_free(sql, "SCHEMA") do |result|
21
21
  rows_from(result).map(&:first)
22
22
  end
23
23
  end
24
24
 
25
- def views(name = nil) #:nodoc:
25
+ def views(name = nil) # :nodoc:
26
26
  result = execute("SHOW FULL TABLES WHERE TABLE_TYPE='VIEW'")
27
27
 
28
28
  rows_from(result).map(&:first)
@@ -37,7 +37,7 @@ module Spectacles
37
37
  raise "No view called #{view} found, #{e}"
38
38
  end
39
39
 
40
- private
40
+ private
41
41
 
42
42
  def rows_from(result)
43
43
  result.respond_to?(:rows) ? result.rows : result