good_migrations 0.0.2 → 0.1.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 +5 -5
- data/.github/workflows/ruby.yml +32 -0
- data/.gitignore +0 -1
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +113 -0
- data/LICENSE.txt +1 -1
- data/README.md +21 -3
- data/Rakefile +3 -2
- data/example/Gemfile +5 -5
- data/example/Rakefile +2 -2
- data/example/app/assets/config/manifest.js +0 -0
- data/example/app/models/pant.rb +0 -1
- data/example/bin/rails +4 -0
- data/example/bin/rake +4 -0
- data/example/config.ru +1 -1
- data/example/config/application.rb +7 -2
- data/example/config/boot.rb +13 -11
- data/example/config/environment.rb +1 -1
- data/example/config/environments/development.rb +3 -3
- data/example/config/environments/production.rb +1 -1
- data/example/config/environments/test.rb +2 -2
- data/example/config/initializers/secret_token.rb +1 -1
- data/example/config/initializers/session_store.rb +1 -1
- data/example/db/migrate/20160202162849_create_pants.rb +1 -1
- data/example/db/migrate/20160202163803_change_pants.rb +2 -1
- data/example/db/migrate/20160202182520_change_pants_dangerously.rb +1 -1
- data/example/lib/tasks/load_pants.rake +5 -0
- data/example/script/rails +3 -3
- data/example/test/performance/browsing_test.rb +3 -3
- data/example/test/test_helper.rb +2 -2
- data/good_migrations.gemspec +16 -15
- data/lib/good_migrations.rb +2 -0
- data/lib/good_migrations/load_error.rb +1 -1
- data/lib/good_migrations/patches_autoloader.rb +63 -0
- data/lib/good_migrations/prevents_app_load.rb +48 -0
- data/lib/good_migrations/railtie.rb +1 -1
- data/lib/good_migrations/version.rb +1 -1
- data/tasks/good_migrations.rake +9 -54
- metadata +39 -17
- data/.travis.yml +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 957989ed1010171743f14af193d62b5bfbb820e59ad79b42ca16d6b8b51ca948
|
4
|
+
data.tar.gz: 89dc256beca58029d4de2c142834a3069b7b165959055bc4f7ab1721ffea6c82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a2e09ff0b2bf6473ececfa8ca0905eae9a974cd81ff5ea76626e7b5e56693169040472a577551aa44976e2d412e957043a31d47e0ca12b405c8b30a16f506cc
|
7
|
+
data.tar.gz: f2b50907f8826e6c76c03b933a1571b5b523ebb7087ab4854fddb300c27d5ba64d5f75e53f2d5639234bd8de07adff2702ceb0ae61d37744fcd7737ccb0c3323
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ main ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ main ]
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
test:
|
18
|
+
|
19
|
+
runs-on: ubuntu-latest
|
20
|
+
strategy:
|
21
|
+
matrix:
|
22
|
+
ruby-version: ['2.7', '3.0']
|
23
|
+
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v2
|
26
|
+
- name: Set up Ruby
|
27
|
+
uses: ruby/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: ${{ matrix.ruby-version }}
|
30
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
31
|
+
- name: Run tests
|
32
|
+
run: bundle exec rake
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
good_migrations (0.1.0)
|
5
|
+
activerecord (>= 3.1)
|
6
|
+
railties (>= 3.1)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionpack (6.1.4)
|
12
|
+
actionview (= 6.1.4)
|
13
|
+
activesupport (= 6.1.4)
|
14
|
+
rack (~> 2.0, >= 2.0.9)
|
15
|
+
rack-test (>= 0.6.3)
|
16
|
+
rails-dom-testing (~> 2.0)
|
17
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
18
|
+
actionview (6.1.4)
|
19
|
+
activesupport (= 6.1.4)
|
20
|
+
builder (~> 3.1)
|
21
|
+
erubi (~> 1.4)
|
22
|
+
rails-dom-testing (~> 2.0)
|
23
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
24
|
+
activemodel (6.1.4)
|
25
|
+
activesupport (= 6.1.4)
|
26
|
+
activerecord (6.1.4)
|
27
|
+
activemodel (= 6.1.4)
|
28
|
+
activesupport (= 6.1.4)
|
29
|
+
activesupport (6.1.4)
|
30
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
31
|
+
i18n (>= 1.6, < 2)
|
32
|
+
minitest (>= 5.1)
|
33
|
+
tzinfo (~> 2.0)
|
34
|
+
zeitwerk (~> 2.3)
|
35
|
+
ast (2.4.2)
|
36
|
+
builder (3.2.4)
|
37
|
+
coderay (1.1.3)
|
38
|
+
concurrent-ruby (1.1.9)
|
39
|
+
crass (1.0.6)
|
40
|
+
erubi (1.10.0)
|
41
|
+
i18n (1.8.10)
|
42
|
+
concurrent-ruby (~> 1.0)
|
43
|
+
loofah (2.10.0)
|
44
|
+
crass (~> 1.0.2)
|
45
|
+
nokogiri (>= 1.5.9)
|
46
|
+
method_source (1.0.0)
|
47
|
+
mini_portile2 (2.5.3)
|
48
|
+
minitest (5.14.4)
|
49
|
+
nokogiri (1.11.7)
|
50
|
+
mini_portile2 (~> 2.5.0)
|
51
|
+
racc (~> 1.4)
|
52
|
+
parallel (1.20.1)
|
53
|
+
parser (3.0.1.1)
|
54
|
+
ast (~> 2.4.1)
|
55
|
+
pry (0.14.1)
|
56
|
+
coderay (~> 1.1)
|
57
|
+
method_source (~> 1.0)
|
58
|
+
racc (1.5.2)
|
59
|
+
rack (2.2.3)
|
60
|
+
rack-test (1.1.0)
|
61
|
+
rack (>= 1.0, < 3)
|
62
|
+
rails-dom-testing (2.0.3)
|
63
|
+
activesupport (>= 4.2.0)
|
64
|
+
nokogiri (>= 1.6)
|
65
|
+
rails-html-sanitizer (1.3.0)
|
66
|
+
loofah (~> 2.3)
|
67
|
+
railties (6.1.4)
|
68
|
+
actionpack (= 6.1.4)
|
69
|
+
activesupport (= 6.1.4)
|
70
|
+
method_source
|
71
|
+
rake (>= 0.13)
|
72
|
+
thor (~> 1.0)
|
73
|
+
rainbow (3.0.0)
|
74
|
+
rake (13.0.3)
|
75
|
+
regexp_parser (2.1.1)
|
76
|
+
rexml (3.2.5)
|
77
|
+
rubocop (1.17.0)
|
78
|
+
parallel (~> 1.10)
|
79
|
+
parser (>= 3.0.0.0)
|
80
|
+
rainbow (>= 2.2.2, < 4.0)
|
81
|
+
regexp_parser (>= 1.8, < 3.0)
|
82
|
+
rexml
|
83
|
+
rubocop-ast (>= 1.7.0, < 2.0)
|
84
|
+
ruby-progressbar (~> 1.7)
|
85
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
86
|
+
rubocop-ast (1.7.0)
|
87
|
+
parser (>= 3.0.1.1)
|
88
|
+
rubocop-performance (1.11.2)
|
89
|
+
rubocop (>= 1.7.0, < 2.0)
|
90
|
+
rubocop-ast (>= 0.4.0)
|
91
|
+
ruby-progressbar (1.11.0)
|
92
|
+
standard (1.1.2)
|
93
|
+
rubocop (= 1.17.0)
|
94
|
+
rubocop-performance (= 1.11.2)
|
95
|
+
thor (1.1.0)
|
96
|
+
tzinfo (2.0.4)
|
97
|
+
concurrent-ruby (~> 1.0)
|
98
|
+
unicode-display_width (2.0.0)
|
99
|
+
zeitwerk (2.4.2)
|
100
|
+
|
101
|
+
PLATFORMS
|
102
|
+
ruby
|
103
|
+
|
104
|
+
DEPENDENCIES
|
105
|
+
bundler
|
106
|
+
good_migrations!
|
107
|
+
minitest
|
108
|
+
pry
|
109
|
+
rake
|
110
|
+
standard
|
111
|
+
|
112
|
+
BUNDLED WITH
|
113
|
+
2.2.15
|
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2016 Test Double,
|
3
|
+
Copyright (c) 2016-2021 Test Double, Inc.
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
6
|
this software and associated documentation files (the "Software"), to deal in
|
data/README.md
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
# good_migrations
|
2
2
|
|
3
|
-
[](https://travis-ci.org/testdouble/good-migrations)
|
4
|
-
|
5
3
|
This gem prevents Rails from auto-loading app code while it's running migrations,
|
6
4
|
preventing the common mistake of referencing ActiveRecord models from migration
|
7
5
|
code.
|
8
6
|
|
9
7
|
## Usage
|
10
8
|
|
11
|
-
|
9
|
+
**HEADS UP: zeitwerk 2.5.0 is not yet released, so if you're using zeitwerk at
|
10
|
+
all, the gem won't be able to ensure your migrations are safe and you'll see a
|
11
|
+
warning to that effect**
|
12
|
+
|
13
|
+
Add good_migrations to your Gemfile:
|
12
14
|
|
13
15
|
``` ruby
|
14
16
|
gem 'good_migrations'
|
@@ -16,6 +18,15 @@ gem 'good_migrations'
|
|
16
18
|
|
17
19
|
And you're done! That's it.
|
18
20
|
|
21
|
+
## Prerequisites
|
22
|
+
|
23
|
+
This gem requires that your app uses either of these autoloader strategies:
|
24
|
+
|
25
|
+
* The classic `ActiveSupport::Dependencies` autoloader (e.g. `config.autoloader
|
26
|
+
= :classic`), which is going away with Rails 7
|
27
|
+
* Version 2.5 or higher of the zeitwerk autoloader (e.g. `config.autoloader =
|
28
|
+
:zeitwerk`) If your app uses an earlier version of zeitwerk, you'll see a
|
29
|
+
warning every time `db:migrate` is run
|
19
30
|
|
20
31
|
## Background
|
21
32
|
|
@@ -63,3 +74,10 @@ have a few options:
|
|
63
74
|
Credit for figuring out where to hook into the ActiveSupport autoloader goes
|
64
75
|
to [@tenderlove](https://github.com/tenderlove) for [this
|
65
76
|
gist](https://gist.github.com/tenderlove/44447d1b1e466a28eb3f).
|
77
|
+
|
78
|
+
## Caveats
|
79
|
+
|
80
|
+
Because this gem works by monkey-patching the ActiveSupport auto-loader, it will
|
81
|
+
not work if your Rails environment (development, by default) is configured to
|
82
|
+
eager load your application's classes (see:
|
83
|
+
[config.eager_load](http://edgeguides.rubyonrails.org/configuring.html#rails-general-configuration)).
|
data/Rakefile
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rake/testtask"
|
3
|
+
require "standard/rake"
|
3
4
|
|
4
5
|
Rake::TestTask.new(:test) do |t|
|
5
6
|
t.libs << "test"
|
6
7
|
t.libs << "lib"
|
7
|
-
t.test_files = FileList[
|
8
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
8
9
|
end
|
9
10
|
|
10
|
-
task :
|
11
|
+
task default: ["standard:fix", :test]
|
data/example/Gemfile
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
|
-
|
4
|
-
gem 'rails', rails_version
|
3
|
+
gem "rails", "~> 6.1"
|
5
4
|
|
6
|
-
gem
|
5
|
+
gem "good_migrations", path: ".."
|
7
6
|
|
8
|
-
gem
|
7
|
+
gem "sqlite3"
|
9
8
|
|
9
|
+
gem "zeitwerk", github: "fxn/zeitwerk"
|
data/example/Rakefile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
2
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
3
|
|
4
|
-
require File.expand_path(
|
5
|
-
require
|
4
|
+
require File.expand_path("../config/application", __FILE__)
|
5
|
+
require "rake"
|
6
6
|
|
7
7
|
Example::Application.load_tasks
|
File without changes
|
data/example/app/models/pant.rb
CHANGED
data/example/bin/rails
ADDED
data/example/bin/rake
ADDED
data/example/config.ru
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require File.expand_path(
|
1
|
+
require File.expand_path("../boot", __FILE__)
|
2
2
|
|
3
|
-
require
|
3
|
+
require "rails/all"
|
4
4
|
|
5
5
|
# If you have a Gemfile, require the gems listed there, including any gems
|
6
6
|
# you've limited to :test, :development, or :production.
|
@@ -8,6 +8,9 @@ Bundler.require(:default, Rails.env) if defined?(Bundler)
|
|
8
8
|
|
9
9
|
module Example
|
10
10
|
class Application < Rails::Application
|
11
|
+
if config.respond_to?("eager_load=")
|
12
|
+
config.eager_load = false
|
13
|
+
end
|
11
14
|
# Settings in config/environments/* take precedence over those specified here.
|
12
15
|
# Application configuration should go into files in config/initializers
|
13
16
|
# -- all .rb files in that directory are automatically loaded.
|
@@ -38,5 +41,7 @@ module Example
|
|
38
41
|
|
39
42
|
# Configure sensitive parameters which will be filtered from the log file.
|
40
43
|
config.filter_parameters += [:password]
|
44
|
+
|
45
|
+
config.autoloader = ENV["AUTOLOADER"] == "zeitwerk" ? :zeitwerk : :classic
|
41
46
|
end
|
42
47
|
end
|
data/example/config/boot.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
-
require
|
1
|
+
require "rubygems"
|
2
2
|
|
3
3
|
# Set up gems listed in the Gemfile.
|
4
|
-
gemfile = File.expand_path(
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
4
|
+
gemfile = File.expand_path("../../Gemfile", __FILE__)
|
5
|
+
if File.exist?(gemfile)
|
6
|
+
begin
|
7
|
+
ENV["BUNDLE_GEMFILE"] = gemfile
|
8
|
+
require "bundler"
|
9
|
+
Bundler.setup
|
10
|
+
rescue Bundler::GemNotFound => e
|
11
|
+
warn e.message
|
12
|
+
warn "Try running `bundle install`."
|
13
|
+
exit!
|
14
|
+
end
|
15
|
+
end
|
@@ -10,8 +10,7 @@ Example::Application.configure do
|
|
10
10
|
config.whiny_nils = true
|
11
11
|
|
12
12
|
# Show full error reports and disable caching
|
13
|
-
config.consider_all_requests_local
|
14
|
-
config.action_view.debug_rjs = true
|
13
|
+
config.consider_all_requests_local = true
|
15
14
|
config.action_controller.perform_caching = false
|
16
15
|
|
17
16
|
# Don't care if the mailer can't send
|
@@ -22,5 +21,6 @@ Example::Application.configure do
|
|
22
21
|
|
23
22
|
# Only use best-standards-support built into browsers
|
24
23
|
config.action_dispatch.best_standards_support = :builtin
|
25
|
-
end
|
26
24
|
|
25
|
+
config.active_record.migration_error = false
|
26
|
+
end
|
@@ -6,7 +6,7 @@ Example::Application.configure do
|
|
6
6
|
config.cache_classes = true
|
7
7
|
|
8
8
|
# Full error reports are disabled and caching is turned on
|
9
|
-
config.consider_all_requests_local
|
9
|
+
config.consider_all_requests_local = false
|
10
10
|
config.action_controller.perform_caching = true
|
11
11
|
|
12
12
|
# Specifies the header that your server uses for sending files
|
@@ -11,14 +11,14 @@ Example::Application.configure do
|
|
11
11
|
config.whiny_nils = true
|
12
12
|
|
13
13
|
# Show full error reports and disable caching
|
14
|
-
config.consider_all_requests_local
|
14
|
+
config.consider_all_requests_local = true
|
15
15
|
config.action_controller.perform_caching = false
|
16
16
|
|
17
17
|
# Raise exceptions instead of rendering exception templates
|
18
18
|
config.action_dispatch.show_exceptions = false
|
19
19
|
|
20
20
|
# Disable request forgery protection in test environment
|
21
|
-
config.action_controller.allow_forgery_protection
|
21
|
+
config.action_controller.allow_forgery_protection = false
|
22
22
|
|
23
23
|
# Tell Action Mailer not to deliver emails to the real world.
|
24
24
|
# The :test delivery method accumulates sent emails in the
|
@@ -4,4 +4,4 @@
|
|
4
4
|
# If you change this key, all old signed cookies will become invalid!
|
5
5
|
# Make sure the secret is at least 30 characters and all random,
|
6
6
|
# no regular words or you'll be exposed to dictionary attacks.
|
7
|
-
Example::Application.config.secret_token =
|
7
|
+
Example::Application.config.secret_token = "5b687ab969ef4f33a41125ae95e73c368d1c391045639df9a1690221b13f8b8cbeb515db9cf5990548af5c309b8d3ab206648837001866cdf854278030285e3c"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Be sure to restart your server when you modify this file.
|
2
2
|
|
3
|
-
Example::Application.config.session_store :cookie_store, :
|
3
|
+
Example::Application.config.session_store :cookie_store, key: "_example_session"
|
4
4
|
|
5
5
|
# Use the database for sessions instead of the cookie-based default,
|
6
6
|
# which shouldn't be used to store highly confidential information
|
data/example/script/rails
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
3
3
|
|
4
|
-
APP_PATH = File.expand_path(
|
5
|
-
require File.expand_path(
|
6
|
-
require
|
4
|
+
APP_PATH = File.expand_path("../../config/application", __FILE__)
|
5
|
+
require File.expand_path("../../config/boot", __FILE__)
|
6
|
+
require "rails/commands"
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "test_helper"
|
2
|
+
require "rails/performance_test_help"
|
3
3
|
|
4
4
|
# Profiling results for each test method are written to tmp/performance.
|
5
5
|
class BrowsingTest < ActionDispatch::PerformanceTest
|
6
6
|
def test_homepage
|
7
|
-
get
|
7
|
+
get "/"
|
8
8
|
end
|
9
9
|
end
|
data/example/test/test_helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
ENV["RAILS_ENV"] = "test"
|
2
|
-
require File.expand_path(
|
3
|
-
require
|
2
|
+
require File.expand_path("../../config/environment", __FILE__)
|
3
|
+
require "rails/test_help"
|
4
4
|
|
5
5
|
class ActiveSupport::TestCase
|
6
6
|
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
|
data/good_migrations.gemspec
CHANGED
@@ -1,28 +1,29 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
3
|
+
require "good_migrations/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.authors
|
10
|
-
spec.email
|
6
|
+
spec.name = "good_migrations"
|
7
|
+
spec.version = GoodMigrations::VERSION
|
8
|
+
spec.authors = ["Justin Searls", "Kevin Baribeau"]
|
9
|
+
spec.email = ["searls@gmail.com", "kevin.baribeau@gmail.com"]
|
11
10
|
|
12
|
-
spec.summary
|
13
|
-
spec.description
|
14
|
-
spec.homepage
|
11
|
+
spec.summary = "Prevents Rails from auto-loading app code in database migrations"
|
12
|
+
spec.description = "Referencing code in app/ from a database migration risks breaking the migration when your app code changes; this gem prevents that mistake"
|
13
|
+
spec.homepage = "https://github.com/testdouble/good-migrations"
|
14
|
+
spec.license = "MIT"
|
15
15
|
|
16
|
-
spec.files
|
17
|
-
spec.bindir
|
18
|
-
spec.executables
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "railties", ">= 3.1"
|
22
22
|
spec.add_dependency "activerecord", ">= 3.1"
|
23
23
|
|
24
|
-
spec.add_development_dependency "bundler"
|
25
|
-
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "bundler"
|
25
|
+
spec.add_development_dependency "rake"
|
26
26
|
spec.add_development_dependency "minitest"
|
27
27
|
spec.add_development_dependency "pry"
|
28
|
+
spec.add_development_dependency "standard"
|
28
29
|
end
|
data/lib/good_migrations.rb
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
module GoodMigrations
|
2
|
+
class PatchesAutoloader
|
3
|
+
def self.instance
|
4
|
+
@instance ||= new
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@disabled = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def disabled?
|
12
|
+
@disabled
|
13
|
+
end
|
14
|
+
|
15
|
+
def patch!
|
16
|
+
if Rails.singleton_class.method_defined?(:autoloaders) &&
|
17
|
+
Rails.autoloaders.zeitwerk_enabled?
|
18
|
+
if Rails.autoloaders.main.respond_to?(:on_load) &&
|
19
|
+
Rails.autoloaders.main.method(:on_load).arity <= 0
|
20
|
+
@disabled = false
|
21
|
+
Rails.autoloaders.each do |loader|
|
22
|
+
loader.on_load do |_, _, path|
|
23
|
+
if GoodMigrations::PreventsAppLoad.app_path?(path) &&
|
24
|
+
!GoodMigrations::PatchesAutoloader.instance.disabled?
|
25
|
+
GoodMigrations::PreventsAppLoad.prevent_load!(path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
else
|
30
|
+
warn <<~UNSUPPORTED
|
31
|
+
WARNING: good_migrations is unable to ensure that your migrations are
|
32
|
+
not inadvertently loading application code, because your application
|
33
|
+
uses the zeitwerk autoloader (`config.autoloader = :zeitwerk`), but
|
34
|
+
is using a version prior to zeitwerk 2.5.0, which adds an on_load
|
35
|
+
hook that good_migrations can latch onto.
|
36
|
+
|
37
|
+
Solution: Ensure that zeitwerk isn't pinned below 2.5.0 in your
|
38
|
+
Gemfile and try running `bundle update zeitwerk`.
|
39
|
+
|
40
|
+
UNSUPPORTED
|
41
|
+
end
|
42
|
+
else
|
43
|
+
@disabled = false
|
44
|
+
ActiveSupport::Dependencies.class_eval do
|
45
|
+
extend Module.new {
|
46
|
+
def load_file(path, const_paths = loadable_constants_for_path(path))
|
47
|
+
if GoodMigrations::PreventsAppLoad.app_path?(path) &&
|
48
|
+
!GoodMigrations::PatchesAutoloader.instance.disabled?
|
49
|
+
GoodMigrations::PreventsAppLoad.prevent_load!(path)
|
50
|
+
else
|
51
|
+
super
|
52
|
+
end
|
53
|
+
end
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def unpatch!
|
60
|
+
@disabled = true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module GoodMigrations
|
2
|
+
class PreventsAppLoad
|
3
|
+
def self.app_path?(path)
|
4
|
+
path.starts_with? File.join(Rails.application.root, "app")
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.prevent_load!(path)
|
8
|
+
raise GoodMigrations::LoadError, <<~ERROR
|
9
|
+
Rails attempted to auto-load:
|
10
|
+
|
11
|
+
#{path}
|
12
|
+
|
13
|
+
Which is in your project's `app/` directory. The good_migrations
|
14
|
+
gem was designed to prevent this, because migrations are intended
|
15
|
+
to be immutable and safe-to-run for the life of your project, but
|
16
|
+
code in `app/` is liable to change at any time.
|
17
|
+
|
18
|
+
The most common reason for this error is that you may be referencing an
|
19
|
+
ActiveRecord model inside the migration in order to use the ActiveRecord API
|
20
|
+
to implement a data migration by querying and updating objects.
|
21
|
+
|
22
|
+
For instance, if you want to access a model "User" in your migration, it's safer
|
23
|
+
to redefine the class inside the migration instead, like this:
|
24
|
+
|
25
|
+
class MakeUsersOlder < ActiveRecord::Migration
|
26
|
+
class User < ActiveRecord::Base
|
27
|
+
# Define whatever you need on the User beyond what AR adds automatically
|
28
|
+
end
|
29
|
+
|
30
|
+
def up
|
31
|
+
User.find_each do |user|
|
32
|
+
user.update!(:age => user.age + 1)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def down
|
37
|
+
#...
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
For more information, visit:
|
42
|
+
|
43
|
+
https://github.com/testdouble/good-migrations
|
44
|
+
|
45
|
+
ERROR
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -3,7 +3,7 @@ require "active_record/railtie"
|
|
3
3
|
module GoodMigrations
|
4
4
|
class Railtie < Rails::Railtie
|
5
5
|
rake_tasks do
|
6
|
-
Dir[File.join(File.dirname(__FILE__),
|
6
|
+
Dir[File.join(File.dirname(__FILE__), "../../tasks/*.rake")].each do |file|
|
7
7
|
load file
|
8
8
|
end
|
9
9
|
end
|
data/tasks/good_migrations.rake
CHANGED
@@ -1,63 +1,18 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "active_support/dependencies"
|
2
|
+
require "good_migrations"
|
3
3
|
|
4
4
|
namespace :good_migrations do
|
5
5
|
task :disable_autoload do
|
6
|
-
next if ENV[
|
7
|
-
|
8
|
-
extend Module.new {
|
9
|
-
def load_file(path, const_paths = loadable_constants_for_path(path))
|
10
|
-
if path.starts_with? File.join(Rails.application.root, 'app')
|
11
|
-
raise GoodMigrations::LoadError, <<-ERROR
|
12
|
-
Rails attempted to auto-load:
|
13
|
-
|
14
|
-
#{path}
|
15
|
-
|
16
|
-
Which is in your project's `app/` directory. The good_migrations
|
17
|
-
gem was designed to prevent this, because migrations are intended
|
18
|
-
to be immutable and safe-to-run for the life of your project, but
|
19
|
-
code in `app/` is liable to change at any time.
|
20
|
-
|
21
|
-
The most common reason for this error is that you may be referencing an
|
22
|
-
ActiveRecord model inside the migration in order to use the ActiveRecord API
|
23
|
-
to implement a data migration by querying and updating objects.
|
24
|
-
|
25
|
-
For instance, if you want to access a model "User" in your migration, it's safer
|
26
|
-
to redefine the class inside the migration instead, like this:
|
27
|
-
|
28
|
-
class MakeUsersOlder < ActiveRecord::Migration
|
29
|
-
class User < ActiveRecord::Base
|
30
|
-
# Define whatever you need on the User beyond what AR adds automatically
|
31
|
-
end
|
32
|
-
|
33
|
-
def up
|
34
|
-
User.find_each do |user|
|
35
|
-
user.update!(:age => user.age + 1)
|
36
|
-
end
|
6
|
+
next if ENV["GOOD_MIGRATIONS"] == "skip"
|
7
|
+
GoodMigrations::PatchesAutoloader.instance.patch!
|
37
8
|
end
|
38
9
|
|
39
|
-
|
40
|
-
|
10
|
+
task :reenable_autoload do
|
11
|
+
next if ENV["GOOD_MIGRATIONS"] == "skip"
|
12
|
+
GoodMigrations::PatchesAutoloader.instance.unpatch!
|
41
13
|
end
|
42
14
|
end
|
43
15
|
|
44
|
-
|
45
|
-
|
46
|
-
https://github.com/testdouble/good-migrations
|
47
|
-
|
48
|
-
ERROR
|
49
|
-
else
|
50
|
-
super
|
51
|
-
end
|
52
|
-
end
|
53
|
-
}
|
54
|
-
end
|
55
|
-
end
|
16
|
+
Rake::Task["db:migrate"].enhance(["good_migrations:disable_autoload"]) do
|
17
|
+
Rake::Task["good_migrations:reenable_autoload"].invoke
|
56
18
|
end
|
57
|
-
|
58
|
-
Rake.application.in_namespace('db:migrate') do |namespace|
|
59
|
-
([Rake::Task['db:migrate']] + namespace.tasks).each do |task|
|
60
|
-
task.prerequisites << "good_migrations:disable_autoload"
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: good_migrations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Searls
|
8
8
|
- Kevin Baribeau
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-06-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: railties
|
@@ -43,30 +43,30 @@ dependencies:
|
|
43
43
|
name: bundler
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - "
|
46
|
+
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
48
|
+
version: '0'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- - "
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rake
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- - "
|
60
|
+
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
62
|
+
version: '0'
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- - "
|
67
|
+
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '0'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: minitest
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,6 +95,20 @@ dependencies:
|
|
95
95
|
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: standard
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
98
112
|
description: Referencing code in app/ from a database migration risks breaking the
|
99
113
|
migration when your app code changes; this gem prevents that mistake
|
100
114
|
email:
|
@@ -104,9 +118,11 @@ executables: []
|
|
104
118
|
extensions: []
|
105
119
|
extra_rdoc_files: []
|
106
120
|
files:
|
121
|
+
- ".github/workflows/ruby.yml"
|
107
122
|
- ".gitignore"
|
108
|
-
-
|
123
|
+
- CHANGELOG.md
|
109
124
|
- Gemfile
|
125
|
+
- Gemfile.lock
|
110
126
|
- LICENSE.txt
|
111
127
|
- README.md
|
112
128
|
- Rakefile
|
@@ -116,10 +132,13 @@ files:
|
|
116
132
|
- example/Gemfile
|
117
133
|
- example/README
|
118
134
|
- example/Rakefile
|
135
|
+
- example/app/assets/config/manifest.js
|
119
136
|
- example/app/controllers/application_controller.rb
|
120
137
|
- example/app/helpers/application_helper.rb
|
121
138
|
- example/app/models/pant.rb
|
122
139
|
- example/app/views/layouts/application.html.erb
|
140
|
+
- example/bin/rails
|
141
|
+
- example/bin/rake
|
123
142
|
- example/config.ru
|
124
143
|
- example/config/application.rb
|
125
144
|
- example/config/boot.rb
|
@@ -141,6 +160,7 @@ files:
|
|
141
160
|
- example/db/seeds.rb
|
142
161
|
- example/doc/README_FOR_APP
|
143
162
|
- example/lib/tasks/.gitkeep
|
163
|
+
- example/lib/tasks/load_pants.rake
|
144
164
|
- example/public/404.html
|
145
165
|
- example/public/422.html
|
146
166
|
- example/public/500.html
|
@@ -162,13 +182,16 @@ files:
|
|
162
182
|
- good_migrations.gemspec
|
163
183
|
- lib/good_migrations.rb
|
164
184
|
- lib/good_migrations/load_error.rb
|
185
|
+
- lib/good_migrations/patches_autoloader.rb
|
186
|
+
- lib/good_migrations/prevents_app_load.rb
|
165
187
|
- lib/good_migrations/railtie.rb
|
166
188
|
- lib/good_migrations/version.rb
|
167
189
|
- tasks/good_migrations.rake
|
168
190
|
homepage: https://github.com/testdouble/good-migrations
|
169
|
-
licenses:
|
191
|
+
licenses:
|
192
|
+
- MIT
|
170
193
|
metadata: {}
|
171
|
-
post_install_message:
|
194
|
+
post_install_message:
|
172
195
|
rdoc_options: []
|
173
196
|
require_paths:
|
174
197
|
- lib
|
@@ -183,9 +206,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
206
|
- !ruby/object:Gem::Version
|
184
207
|
version: '0'
|
185
208
|
requirements: []
|
186
|
-
|
187
|
-
|
188
|
-
signing_key:
|
209
|
+
rubygems_version: 3.2.15
|
210
|
+
signing_key:
|
189
211
|
specification_version: 4
|
190
212
|
summary: Prevents Rails from auto-loading app code in database migrations
|
191
213
|
test_files: []
|