capture_migration_sql 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d363515469587ed28cbf2f3b5e63f62fac816ef666c3068739e0a9daace3ba7d
4
+ data.tar.gz: 572ae7848eaad194e7785951b8df034be4be5afa1a433257d84b22acd85de512
5
+ SHA512:
6
+ metadata.gz: eb3f14254f65d4008bc689f4921b85ea8900eef141e0256153419716d276c8d50cddd06881aa8a83d0d92e15311decb46fa8bde7710035fb0a9300328e9ebd6f
7
+ data.tar.gz: 8b147b725d0e0a1d3962deceb68b077a329639479ac94e6e2ad94177df6de750f056f58eb37990becdab2dcb5e6ae3c7674f5a827bb32032594bb8ce34bffba6
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ .DS_Store
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
data/.travis.yml ADDED
@@ -0,0 +1,22 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.5
4
+ - 2.3
5
+
6
+ cache: bundler
7
+
8
+ branches:
9
+ # Only build master and release version tags
10
+ only:
11
+ - master
12
+ - /^v\d+\.\d+(\.\d+)?(-\S*)?$/
13
+
14
+ gemfile:
15
+ - Gemfile
16
+ - gemfiles/activerecord_5.2.gemfile
17
+ - gemfiles/activerecord_5.1.gemfile
18
+ - gemfiles/activerecord_5.0.gemfile
19
+ - gemfiles/activerecord_4.2.gemfile
20
+
21
+ script:
22
+ - bundle exec rake spec
data/Appraisals ADDED
@@ -0,0 +1,7 @@
1
+ RAILS_MINOR_RELEASES = ["5.2", "5.1", "5.0", "4.2"].freeze
2
+
3
+ RAILS_MINOR_RELEASES.each do |version|
4
+ appraise "activerecord-#{version}" do
5
+ gem "activerecord", "~> #{version}.0"
6
+ end
7
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ # 1.0.1
2
+ * Fix SQL for insterting into schema_migrations
3
+
4
+ # 1.0.0
5
+
6
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in capture_migration_sql.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,65 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ capture_migration_sql (1.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ activemodel (5.2.1)
10
+ activesupport (= 5.2.1)
11
+ activerecord (5.2.1)
12
+ activemodel (= 5.2.1)
13
+ activesupport (= 5.2.1)
14
+ arel (>= 9.0)
15
+ activesupport (5.2.1)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 0.7, < 2)
18
+ minitest (~> 5.1)
19
+ tzinfo (~> 1.1)
20
+ appraisal (2.2.0)
21
+ bundler
22
+ rake
23
+ thor (>= 0.14.0)
24
+ arel (9.0.0)
25
+ concurrent-ruby (1.0.5)
26
+ database_cleaner (1.7.0)
27
+ diff-lcs (1.3)
28
+ i18n (1.1.1)
29
+ concurrent-ruby (~> 1.0)
30
+ minitest (5.11.3)
31
+ rake (10.5.0)
32
+ rspec (3.8.0)
33
+ rspec-core (~> 3.8.0)
34
+ rspec-expectations (~> 3.8.0)
35
+ rspec-mocks (~> 3.8.0)
36
+ rspec-core (3.8.0)
37
+ rspec-support (~> 3.8.0)
38
+ rspec-expectations (3.8.2)
39
+ diff-lcs (>= 1.2.0, < 2.0)
40
+ rspec-support (~> 3.8.0)
41
+ rspec-mocks (3.8.0)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.8.0)
44
+ rspec-support (3.8.0)
45
+ sqlite3 (1.3.13)
46
+ thor (0.20.0)
47
+ thread_safe (0.3.6)
48
+ tzinfo (1.2.5)
49
+ thread_safe (~> 0.1)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ activerecord (>= 4.2)
56
+ appraisal
57
+ bundler (~> 1.16)
58
+ capture_migration_sql!
59
+ database_cleaner
60
+ rake (~> 10.0)
61
+ rspec (~> 3.0)
62
+ sqlite3
63
+
64
+ BUNDLED WITH
65
+ 1.16.5
data/MIT_LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Brian Durand
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,82 @@
1
+ # CaptureMigrationSql
2
+
3
+ [![Build Status](https://travis-ci.com/bdurand/capture_migration_sql.svg?branch=master)](https://travis-ci.com/bdurand/capture_migration_sql)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/17bbf5cb6eda022028fe/maintainability)](https://codeclimate.com/github/bdurand/capture_migration_sql/maintainability)
5
+
6
+ This gem adds the ability to capture and persist the SQL statements executed by migrations. There are a couple of reasons why you may want to do this.
7
+
8
+ 1. Having a list of SQL changes in a migration can allow a more thorough review of database changes during a code review. The Ruby schema directives in Rails are nice for simple tables and for documentation purposes, but if you need to tune your database for performance or data integrity, seeing the raw SQL can give you a better idea of exactly what each change involves.
9
+
10
+ 2. Not everyone gets to run database migrations in production. If you have a DBA who needs to approve and run all changes for security and performance reasons, you'll probably need to give them the individual SQL changes. This gem logs all those changes for you in a consistent place so you don't have to hunt for them in your development logs or reverse engineer them from the Ruby code.
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'capture_migration_sql'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install capture_migration_sql
27
+
28
+ ## Usage
29
+
30
+ Add this to a file in `config/initializers` in your Rails application:
31
+
32
+ ```ruby
33
+ CaptureMigrationSql.capture
34
+ ```
35
+
36
+ This will log each migration to a file in the `db/migration_sql` directory. You can also specify a different directory by passing the path the the `capture` method. Additionally, you can specify a first migration to start with. This will avoid generating files for all previous versions.
37
+
38
+ ```ruby
39
+ # Create all files in the directory 'tmp/migration_sql'
40
+ CaptureMigrationSql.capture(directory: "tmp/migration_sql")
41
+
42
+ # Only capture migrations starting with version 20181010081254
43
+ CaptureMigrationSql.capture(starting_with: 20181010081254)
44
+ ```
45
+
46
+ Within a migration, you can enable and disable capturing SQL within a block:
47
+
48
+ ```ruby
49
+ def up
50
+ disable_sql_logging do
51
+ # SQL will not be logged here
52
+
53
+ enable_sql_logging do
54
+ # SQL will be logged here
55
+ end
56
+
57
+ # SQL will not be logged here
58
+ end
59
+ end
60
+ ```
61
+
62
+ You should disable SQL logging in migration logic that generate queries to clean up or move data that may result in different results per environment. For instance a block of code that selects rows from an existing table and munges the data for an update would result in different queries for each developer that ran the migration if they had different data in their local database.
63
+
64
+ Finally, if you application uses multiple databases, you can specify which database connection to use for schema statements within a block. You can also specify an optional label that will be added as a comment in the SQL file.
65
+
66
+ ```ruby
67
+ def up
68
+ using_connection(other_database_connection, label: "Comment for file") do
69
+ # schema statements here will use other_database_connection instead of ActiveRecord::Base.connection
70
+ end
71
+ end
72
+ ```
73
+
74
+ You can either pass in a database connection object or a class that extends from `ActiveRecord::Base`
75
+
76
+ ## Contributing
77
+
78
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bdurand/capture_migration_sql.
79
+
80
+ ## License
81
+
82
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :appraisals
7
+
8
+ desc "run the specs using appraisal"
9
+ task :appraisals do
10
+ exec "bundle exec appraisal rake spec"
11
+ end
12
+
13
+ namespace :appraisals do
14
+ desc "install all the appraisal gemspecs"
15
+ task :install do
16
+ exec "bundle exec appraisal install"
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "capture_migration_sql/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "capture_migration_sql"
9
+ spec.version = CaptureMigrationSql::VERSION
10
+ spec.authors = ["Brian Durand"]
11
+ spec.email = ["bbdurand@gmail.com"]
12
+
13
+ spec.summary = %q{Capture the SQL that is executed when running ActiveRecord migrations so that it can be run in in other environments that don't support migrations.}
14
+ spec.homepage = "https://github.com/bdurand/capture_migration_sql"
15
+ spec.license = "MIT"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.16"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rspec", "~> 3.0"
29
+ spec.add_development_dependency "activerecord", ">= 4.2"
30
+ spec.add_development_dependency "database_cleaner"
31
+ spec.add_development_dependency "sqlite3"
32
+ spec.add_development_dependency "appraisal"
33
+ end
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_RETRY: "1"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 4.2.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,67 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ capture_migration_sql (1.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ activemodel (4.2.10)
10
+ activesupport (= 4.2.10)
11
+ builder (~> 3.1)
12
+ activerecord (4.2.10)
13
+ activemodel (= 4.2.10)
14
+ activesupport (= 4.2.10)
15
+ arel (~> 6.0)
16
+ activesupport (4.2.10)
17
+ i18n (~> 0.7)
18
+ minitest (~> 5.1)
19
+ thread_safe (~> 0.3, >= 0.3.4)
20
+ tzinfo (~> 1.1)
21
+ appraisal (2.2.0)
22
+ bundler
23
+ rake
24
+ thor (>= 0.14.0)
25
+ arel (6.0.4)
26
+ builder (3.2.3)
27
+ concurrent-ruby (1.0.5)
28
+ database_cleaner (1.7.0)
29
+ diff-lcs (1.3)
30
+ i18n (0.9.5)
31
+ concurrent-ruby (~> 1.0)
32
+ minitest (5.11.3)
33
+ rake (10.5.0)
34
+ rspec (3.8.0)
35
+ rspec-core (~> 3.8.0)
36
+ rspec-expectations (~> 3.8.0)
37
+ rspec-mocks (~> 3.8.0)
38
+ rspec-core (3.8.0)
39
+ rspec-support (~> 3.8.0)
40
+ rspec-expectations (3.8.1)
41
+ diff-lcs (>= 1.2.0, < 2.0)
42
+ rspec-support (~> 3.8.0)
43
+ rspec-mocks (3.8.0)
44
+ diff-lcs (>= 1.2.0, < 2.0)
45
+ rspec-support (~> 3.8.0)
46
+ rspec-support (3.8.0)
47
+ sqlite3 (1.3.13)
48
+ thor (0.20.0)
49
+ thread_safe (0.3.6)
50
+ tzinfo (1.2.5)
51
+ thread_safe (~> 0.1)
52
+
53
+ PLATFORMS
54
+ ruby
55
+
56
+ DEPENDENCIES
57
+ activerecord (~> 4.2.0)
58
+ appraisal
59
+ bundler (~> 1.16)
60
+ capture_migration_sql!
61
+ database_cleaner
62
+ rake (~> 10.0)
63
+ rspec (~> 3.0)
64
+ sqlite3
65
+
66
+ BUNDLED WITH
67
+ 1.16.5
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.0.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,65 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ capture_migration_sql (1.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ activemodel (5.0.7)
10
+ activesupport (= 5.0.7)
11
+ activerecord (5.0.7)
12
+ activemodel (= 5.0.7)
13
+ activesupport (= 5.0.7)
14
+ arel (~> 7.0)
15
+ activesupport (5.0.7)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 0.7, < 2)
18
+ minitest (~> 5.1)
19
+ tzinfo (~> 1.1)
20
+ appraisal (2.2.0)
21
+ bundler
22
+ rake
23
+ thor (>= 0.14.0)
24
+ arel (7.1.4)
25
+ concurrent-ruby (1.0.5)
26
+ database_cleaner (1.7.0)
27
+ diff-lcs (1.3)
28
+ i18n (1.1.0)
29
+ concurrent-ruby (~> 1.0)
30
+ minitest (5.11.3)
31
+ rake (10.5.0)
32
+ rspec (3.8.0)
33
+ rspec-core (~> 3.8.0)
34
+ rspec-expectations (~> 3.8.0)
35
+ rspec-mocks (~> 3.8.0)
36
+ rspec-core (3.8.0)
37
+ rspec-support (~> 3.8.0)
38
+ rspec-expectations (3.8.1)
39
+ diff-lcs (>= 1.2.0, < 2.0)
40
+ rspec-support (~> 3.8.0)
41
+ rspec-mocks (3.8.0)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.8.0)
44
+ rspec-support (3.8.0)
45
+ sqlite3 (1.3.13)
46
+ thor (0.20.0)
47
+ thread_safe (0.3.6)
48
+ tzinfo (1.2.5)
49
+ thread_safe (~> 0.1)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ activerecord (~> 5.0.0)
56
+ appraisal
57
+ bundler (~> 1.16)
58
+ capture_migration_sql!
59
+ database_cleaner
60
+ rake (~> 10.0)
61
+ rspec (~> 3.0)
62
+ sqlite3
63
+
64
+ BUNDLED WITH
65
+ 1.16.5
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.1.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,65 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ capture_migration_sql (1.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ activemodel (5.1.6)
10
+ activesupport (= 5.1.6)
11
+ activerecord (5.1.6)
12
+ activemodel (= 5.1.6)
13
+ activesupport (= 5.1.6)
14
+ arel (~> 8.0)
15
+ activesupport (5.1.6)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 0.7, < 2)
18
+ minitest (~> 5.1)
19
+ tzinfo (~> 1.1)
20
+ appraisal (2.2.0)
21
+ bundler
22
+ rake
23
+ thor (>= 0.14.0)
24
+ arel (8.0.0)
25
+ concurrent-ruby (1.0.5)
26
+ database_cleaner (1.7.0)
27
+ diff-lcs (1.3)
28
+ i18n (1.1.0)
29
+ concurrent-ruby (~> 1.0)
30
+ minitest (5.11.3)
31
+ rake (10.5.0)
32
+ rspec (3.8.0)
33
+ rspec-core (~> 3.8.0)
34
+ rspec-expectations (~> 3.8.0)
35
+ rspec-mocks (~> 3.8.0)
36
+ rspec-core (3.8.0)
37
+ rspec-support (~> 3.8.0)
38
+ rspec-expectations (3.8.1)
39
+ diff-lcs (>= 1.2.0, < 2.0)
40
+ rspec-support (~> 3.8.0)
41
+ rspec-mocks (3.8.0)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.8.0)
44
+ rspec-support (3.8.0)
45
+ sqlite3 (1.3.13)
46
+ thor (0.20.0)
47
+ thread_safe (0.3.6)
48
+ tzinfo (1.2.5)
49
+ thread_safe (~> 0.1)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ activerecord (~> 5.1.0)
56
+ appraisal
57
+ bundler (~> 1.16)
58
+ capture_migration_sql!
59
+ database_cleaner
60
+ rake (~> 10.0)
61
+ rspec (~> 3.0)
62
+ sqlite3
63
+
64
+ BUNDLED WITH
65
+ 1.16.5
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.2.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,65 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ capture_migration_sql (1.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ activemodel (5.2.1)
10
+ activesupport (= 5.2.1)
11
+ activerecord (5.2.1)
12
+ activemodel (= 5.2.1)
13
+ activesupport (= 5.2.1)
14
+ arel (>= 9.0)
15
+ activesupport (5.2.1)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 0.7, < 2)
18
+ minitest (~> 5.1)
19
+ tzinfo (~> 1.1)
20
+ appraisal (2.2.0)
21
+ bundler
22
+ rake
23
+ thor (>= 0.14.0)
24
+ arel (9.0.0)
25
+ concurrent-ruby (1.0.5)
26
+ database_cleaner (1.7.0)
27
+ diff-lcs (1.3)
28
+ i18n (1.1.0)
29
+ concurrent-ruby (~> 1.0)
30
+ minitest (5.11.3)
31
+ rake (10.5.0)
32
+ rspec (3.8.0)
33
+ rspec-core (~> 3.8.0)
34
+ rspec-expectations (~> 3.8.0)
35
+ rspec-mocks (~> 3.8.0)
36
+ rspec-core (3.8.0)
37
+ rspec-support (~> 3.8.0)
38
+ rspec-expectations (3.8.1)
39
+ diff-lcs (>= 1.2.0, < 2.0)
40
+ rspec-support (~> 3.8.0)
41
+ rspec-mocks (3.8.0)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.8.0)
44
+ rspec-support (3.8.0)
45
+ sqlite3 (1.3.13)
46
+ thor (0.20.0)
47
+ thread_safe (0.3.6)
48
+ tzinfo (1.2.5)
49
+ thread_safe (~> 0.1)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ activerecord (~> 5.2.0)
56
+ appraisal
57
+ bundler (~> 1.16)
58
+ capture_migration_sql!
59
+ database_cleaner
60
+ rake (~> 10.0)
61
+ rspec (~> 3.0)
62
+ sqlite3
63
+
64
+ BUNDLED WITH
65
+ 1.16.5
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Extension methods for ActiveRecord::Migration class.
4
+ module CaptureMigrationSql
5
+ module MigrationExtension
6
+ # Monkey patch to public but internal ActiveRecord method to pass
7
+ # a connection that will log SQL statements.
8
+ def exec_migration(conn, direction)
9
+ log_migration_sql(direction) do
10
+ super(conn, direction)
11
+ end
12
+ end
13
+
14
+ # Disable SQL logging. You can use this method to turn off logging SQL
15
+ # when the migration is munging data that may vary between environments.
16
+ def disable_sql_logging(&block)
17
+ sql_logging(enabled: false, &block)
18
+ end
19
+
20
+ # Enable SQL logging. You can call this method within a block where SQL
21
+ # logging was disabled to renable it.
22
+ def enable_sql_logging(&block)
23
+ sql_logging(enabled: true, &block)
24
+ end
25
+
26
+ # Use a different database connection for the block. You can use this
27
+ # if your application has multiple databases to swap connections for
28
+ # the migration. You can pass in either a database connection or an
29
+ # ActiveRecord::Base class to use the connection used by that class.
30
+ #
31
+ # The label argument will be added to the logged SQL as a comment.
32
+ def using_connection(connection_or_class, label: nil, &block)
33
+ if connection_or_class.is_a?(Class) && connection_or_class < ActiveRecord::Base
34
+ label ||= connection_or_class.name
35
+ connection_or_class.connection_pool.with_connection do |connection|
36
+ switch_connection_in_block(connection, label: label, &block)
37
+ end
38
+ else
39
+ switch_connection_in_block(connection_or_class, label: label, &block)
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def switch_connection_in_block(connection, label:, &block)
46
+ save_connection = @connection
47
+ begin
48
+ @connection = connection
49
+ stream = CaptureMigrationSql.capture_stream
50
+ stream.write("-- BEGIN #{label}\n\n") if label && stream
51
+ retval = yield
52
+ stream.write("-- END #{label}\n\n") if label && stream
53
+ retval
54
+ ensure
55
+ @connection = save_connection
56
+ end
57
+ end
58
+
59
+ def sql_logging(enabled:, &block)
60
+ save_val = Thread.current[:capture_migration_sql_enabled]
61
+ begin
62
+ Thread.current[:capture_migration_sql_enabled] = enabled
63
+ yield
64
+ ensure
65
+ Thread.current[:capture_migration_sql_enabled] = save_val
66
+ end
67
+ end
68
+
69
+ def log_migration_sql(direction, &block)
70
+ migration_sql_dir = CaptureMigrationSql.directory
71
+ output_file = File.join(migration_sql_dir, "#{version}_#{name.underscore}.sql") if version && name
72
+ if output_file && direction == :up && version.to_i >= CaptureMigrationSql.starting_with_version
73
+ Dir.mkdir(migration_sql_dir) unless File.exist?(migration_sql_dir)
74
+ SqlSubscriber.attach_if_necessary
75
+ File.open(output_file, "w") do |f|
76
+ f.write("--\n-- #{name} : #{version}\n--\n\n")
77
+ save_stream = Thread.current[:capture_migration_sql_stream]
78
+ begin
79
+ Thread.current[:capture_migration_sql_stream] = f
80
+ sql_logging(enabled: true, &block)
81
+ ensure
82
+ Thread.current[:capture_migration_sql_stream] = save_stream
83
+ end
84
+ f.write("INSERT INTO schema_migrations (version) VALUES #{version.to_i};\n")
85
+ end
86
+ else
87
+ File.unlink(output_file) if output_file && File.exist?(output_file)
88
+ yield
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/subscriber'
4
+
5
+ # Subscriber that is attached to ActiveRecord and will handle writing
6
+ # migration SQL to the output stream.
7
+ module CaptureMigrationSql
8
+ class SqlSubscriber < ::ActiveSupport::Subscriber
9
+ IGNORE_PAYLOAD_NAMES = ["SCHEMA", "EXPLAIN"]
10
+
11
+ SHOW_STATEMENT = /\ASHOW\b/i
12
+ EXPLAIN_STATEMENT = /\AEXPLAIN\b/i
13
+ SELECT_SCHEMA_MIGRATIONS = /\ASELECT.*FROM.*schema_migrations/i
14
+ SELECT_INFORMATION_SCHEMA = /\ASELECT.*information_schema/im
15
+ SQLLITE_VERSION = /\ASELECT sqlite_version\(/i
16
+ IGNORE_STATEMENTS = Regexp.union(SHOW_STATEMENT, EXPLAIN_STATEMENT, SELECT_SCHEMA_MIGRATIONS, SELECT_INFORMATION_SCHEMA, SQLLITE_VERSION)
17
+
18
+ class << self
19
+ def attach_if_necessary
20
+ unless defined?(@attached) && @attached
21
+ attach_to(:active_record)
22
+ @attached = true
23
+ end
24
+ end
25
+ end
26
+
27
+ def sql(event)
28
+ stream = CaptureMigrationSql.capture_stream
29
+ return unless stream && CaptureMigrationSql.capture_enabled?
30
+
31
+ payload = event.payload
32
+ return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
33
+ sql = payload[:sql]
34
+ return if sql.nil? || IGNORE_STATEMENTS.match(sql)
35
+
36
+ sql = sql.strip
37
+ sql = "#{sql};" unless sql.end_with?(";")
38
+ stream.write("#{sql}\n\n")
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CaptureMigrationSql
4
+ VERSION = "1.0.1"
5
+ end
@@ -0,0 +1,46 @@
1
+ require_relative "capture_migration_sql/migration_extension"
2
+ require_relative "capture_migration_sql/sql_subscriber"
3
+ require_relative "capture_migration_sql/version"
4
+
5
+ module CaptureMigrationSql
6
+
7
+ class << self
8
+ # Call this method in an initializer to invoke dumping the SQL executed
9
+ # during migrations in to a file.
10
+ #
11
+ # The `directory` argument indicates the directory where the files should be stored.
12
+ # If the directory is not specified, the files will be stored in `db/migration_sql/`.
13
+ #
14
+ # The `starting_with` argument can be used to specify which migration you
15
+ # wish to start capturing SQL with. This can be useful if you are adding
16
+ # this gem to an existing project with a history of migrations that you
17
+ # don't want to go back and edit.
18
+ def capture(directory: nil, starting_with: 0)
19
+ unless ::ActiveRecord::Migration.include?(MigrationExtension)
20
+ ::ActiveRecord::Migration.prepend(MigrationExtension)
21
+ end
22
+ @sql_directory = (directory || Rails.root + "db" + "migration_sql")
23
+ @starting_with_version = starting_with.to_i
24
+ end
25
+
26
+ # Return the directory set by `capture_sql` for storing migration SQL.
27
+ def directory
28
+ @sql_directory if defined?(@sql_directory)
29
+ end
30
+
31
+ # Return the migration version number to start capaturing SQL.
32
+ def starting_with_version
33
+ @starting_with_version if defined?(@starting_with_version)
34
+ end
35
+
36
+ # Return true if capturing SQL is enabled for migrations.
37
+ def capture_enabled?
38
+ !!Thread.current[:capture_migration_sql_enabled]
39
+ end
40
+
41
+ # Return the strema migration SQL is being written to.
42
+ def capture_stream
43
+ Thread.current[:capture_migration_sql_stream]
44
+ end
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capture_migration_sql
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Brian Durand
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-10-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activerecord
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '4.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '4.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: database_cleaner
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sqlite3
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: appraisal
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description:
112
+ email:
113
+ - bbdurand@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".travis.yml"
120
+ - Appraisals
121
+ - CHANGELOG.md
122
+ - Gemfile
123
+ - Gemfile.lock
124
+ - MIT_LICENSE.txt
125
+ - README.md
126
+ - Rakefile
127
+ - capture_migration_sql.gemspec
128
+ - gemfiles/.bundle/config
129
+ - gemfiles/activerecord_4.2.gemfile
130
+ - gemfiles/activerecord_4.2.gemfile.lock
131
+ - gemfiles/activerecord_5.0.gemfile
132
+ - gemfiles/activerecord_5.0.gemfile.lock
133
+ - gemfiles/activerecord_5.1.gemfile
134
+ - gemfiles/activerecord_5.1.gemfile.lock
135
+ - gemfiles/activerecord_5.2.gemfile
136
+ - gemfiles/activerecord_5.2.gemfile.lock
137
+ - lib/capture_migration_sql.rb
138
+ - lib/capture_migration_sql/migration_extension.rb
139
+ - lib/capture_migration_sql/sql_subscriber.rb
140
+ - lib/capture_migration_sql/version.rb
141
+ homepage: https://github.com/bdurand/capture_migration_sql
142
+ licenses:
143
+ - MIT
144
+ metadata: {}
145
+ post_install_message:
146
+ rdoc_options: []
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ requirements: []
160
+ rubyforge_project:
161
+ rubygems_version: 2.7.6
162
+ signing_key:
163
+ specification_version: 4
164
+ summary: Capture the SQL that is executed when running ActiveRecord migrations so
165
+ that it can be run in in other environments that don't support migrations.
166
+ test_files: []