good_migrations 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +24 -24
- data/README.md +58 -16
- data/example/Gemfile +2 -0
- data/example/app/models/shirt.rb +2 -0
- data/example/config/boot.rb +1 -0
- data/example/config/initializers/good_migrations.rb +7 -0
- data/example/db/migrate/20170101150000_create_shirts.rb +8 -0
- data/example/db/migrate/20170102150000_change_shirts_dangerously.rb +10 -0
- data/lib/good_migrations/configuration.rb +38 -0
- data/lib/good_migrations/migration_details.rb +29 -0
- data/lib/good_migrations/patches_autoloader.rb +11 -13
- data/lib/good_migrations/permits_autoload.rb +19 -0
- data/lib/good_migrations/{prevents_app_load.rb → raises_load_error.rb} +3 -7
- data/lib/good_migrations/version.rb +1 -1
- data/lib/good_migrations.rb +10 -5
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9dee0175ec6d3a50dfbf5b22591311fb571d718c5f7d5fa56ddaa3e07a95860a
|
4
|
+
data.tar.gz: 0c483eb30524bbe3a426f197d40dbb7de049db96b8db30d7835ad97f36e23c86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91d8a48741dd67c0163e5ad85958f6f623be07d36273aa8df78d94cc55a419bd72498dfb34501b7ecbdfba931ce1a20e3ce16c85c84ddb2b2905e5850152a3a5
|
7
|
+
data.tar.gz: 55774f660e0aa7b9671dbcf4d734a1266515e37718045ac561ac076d0c9f8ca8a722b0e1c03e88498f848e3db980a7821bef31c298f14bcece1d300b29484b2a
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
good_migrations (0.
|
4
|
+
good_migrations (0.2.0)
|
5
5
|
activerecord (>= 3.1)
|
6
6
|
railties (>= 3.1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
actionpack (6.1.4)
|
12
|
-
actionview (= 6.1.4)
|
13
|
-
activesupport (= 6.1.4)
|
11
|
+
actionpack (6.1.4.1)
|
12
|
+
actionview (= 6.1.4.1)
|
13
|
+
activesupport (= 6.1.4.1)
|
14
14
|
rack (~> 2.0, >= 2.0.9)
|
15
15
|
rack-test (>= 0.6.3)
|
16
16
|
rails-dom-testing (~> 2.0)
|
17
17
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
18
|
-
actionview (6.1.4)
|
19
|
-
activesupport (= 6.1.4)
|
18
|
+
actionview (6.1.4.1)
|
19
|
+
activesupport (= 6.1.4.1)
|
20
20
|
builder (~> 3.1)
|
21
21
|
erubi (~> 1.4)
|
22
22
|
rails-dom-testing (~> 2.0)
|
23
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)
|
24
|
+
activemodel (6.1.4.1)
|
25
|
+
activesupport (= 6.1.4.1)
|
26
|
+
activerecord (6.1.4.1)
|
27
|
+
activemodel (= 6.1.4.1)
|
28
|
+
activesupport (= 6.1.4.1)
|
29
|
+
activesupport (6.1.4.1)
|
30
30
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
31
31
|
i18n (>= 1.6, < 2)
|
32
32
|
minitest (>= 5.1)
|
@@ -38,16 +38,16 @@ GEM
|
|
38
38
|
concurrent-ruby (1.1.9)
|
39
39
|
crass (1.0.6)
|
40
40
|
erubi (1.10.0)
|
41
|
-
i18n (1.8.
|
41
|
+
i18n (1.8.11)
|
42
42
|
concurrent-ruby (~> 1.0)
|
43
|
-
loofah (2.
|
43
|
+
loofah (2.12.0)
|
44
44
|
crass (~> 1.0.2)
|
45
45
|
nokogiri (>= 1.5.9)
|
46
46
|
method_source (1.0.0)
|
47
|
-
mini_portile2 (2.
|
47
|
+
mini_portile2 (2.6.1)
|
48
48
|
minitest (5.14.4)
|
49
|
-
nokogiri (1.
|
50
|
-
mini_portile2 (~> 2.
|
49
|
+
nokogiri (1.12.5)
|
50
|
+
mini_portile2 (~> 2.6.1)
|
51
51
|
racc (~> 1.4)
|
52
52
|
parallel (1.20.1)
|
53
53
|
parser (3.0.1.1)
|
@@ -55,18 +55,18 @@ GEM
|
|
55
55
|
pry (0.14.1)
|
56
56
|
coderay (~> 1.1)
|
57
57
|
method_source (~> 1.0)
|
58
|
-
racc (1.
|
58
|
+
racc (1.6.0)
|
59
59
|
rack (2.2.3)
|
60
60
|
rack-test (1.1.0)
|
61
61
|
rack (>= 1.0, < 3)
|
62
62
|
rails-dom-testing (2.0.3)
|
63
63
|
activesupport (>= 4.2.0)
|
64
64
|
nokogiri (>= 1.6)
|
65
|
-
rails-html-sanitizer (1.
|
65
|
+
rails-html-sanitizer (1.4.2)
|
66
66
|
loofah (~> 2.3)
|
67
|
-
railties (6.1.4)
|
68
|
-
actionpack (= 6.1.4)
|
69
|
-
activesupport (= 6.1.4)
|
67
|
+
railties (6.1.4.1)
|
68
|
+
actionpack (= 6.1.4.1)
|
69
|
+
activesupport (= 6.1.4.1)
|
70
70
|
method_source
|
71
71
|
rake (>= 0.13)
|
72
72
|
thor (~> 1.0)
|
@@ -96,7 +96,7 @@ GEM
|
|
96
96
|
tzinfo (2.0.4)
|
97
97
|
concurrent-ruby (~> 1.0)
|
98
98
|
unicode-display_width (2.0.0)
|
99
|
-
zeitwerk (2.
|
99
|
+
zeitwerk (2.5.1)
|
100
100
|
|
101
101
|
PLATFORMS
|
102
102
|
ruby
|
@@ -110,4 +110,4 @@ DEPENDENCIES
|
|
110
110
|
standard
|
111
111
|
|
112
112
|
BUNDLED WITH
|
113
|
-
2.2.
|
113
|
+
2.2.30
|
data/README.md
CHANGED
@@ -6,11 +6,7 @@ code.
|
|
6
6
|
|
7
7
|
## Usage
|
8
8
|
|
9
|
-
|
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:
|
9
|
+
Add `good_migrations` to your Gemfile:
|
14
10
|
|
15
11
|
``` ruby
|
16
12
|
gem 'good_migrations'
|
@@ -24,7 +20,7 @@ This gem requires that your app uses either of these autoloader strategies:
|
|
24
20
|
|
25
21
|
* The classic `ActiveSupport::Dependencies` autoloader (e.g. `config.autoloader
|
26
22
|
= :classic`), which is going away with Rails 7
|
27
|
-
* Version 2.5 or higher of the
|
23
|
+
* **Version 2.5 or higher** of the Zeitwerk autoloader (e.g. `config.autoloader =
|
28
24
|
:zeitwerk`) If your app uses an earlier version of zeitwerk, you'll see a
|
29
25
|
warning every time `db:migrate` is run
|
30
26
|
|
@@ -60,24 +56,70 @@ good!
|
|
60
56
|
For more background, see the last section of this blog post on [healthy migration
|
61
57
|
habits](http://blog.testdouble.com/posts/2014-11-04-healthy-migration-habits.html)
|
62
58
|
|
63
|
-
##
|
59
|
+
## Adding to an existing app
|
60
|
+
|
61
|
+
If you add `good_migrations` to an existing application **and** any of those
|
62
|
+
migrations relied on auto-loading code from `app/`, then you'll see errors
|
63
|
+
raised whenever those migrations are run.
|
64
|
+
|
65
|
+
You have several options if this happens:
|
66
|
+
|
67
|
+
* If you're confident that every long-lasting environment has run the latest
|
68
|
+
migrations, you could consider squashing your existing migrations into a
|
69
|
+
single migration file that reflects the current state of your schema. This is
|
70
|
+
a tricky procedure to pull off in complex apps, and can require extra
|
71
|
+
coordination in cases where a high number of contributors are working on the
|
72
|
+
application simultaneously. The
|
73
|
+
[squasher](https://github.com/jalkoby/squasher) gem may be able to help.
|
74
|
+
* You can rewrite those past migrations to inline any application code inside
|
75
|
+
the migration's namespace. One way to do this is to run migrations until they
|
76
|
+
fail, check out the git ref of the failing migration so the codebase is
|
77
|
+
rewound to where it was at the time the migration was written, and finally
|
78
|
+
inline the necessary app code to get the migration passing before checking out
|
79
|
+
your primary branch. Rewriting any migration introduces risk of the resulting
|
80
|
+
schema diverging from production, so this requires significant care and
|
81
|
+
attention
|
82
|
+
* If neither of the above options are feasible, you can configure the
|
83
|
+
`good_migrations` gem to ignore migrations prior to a specified date with the
|
84
|
+
[permit_autoloading_before](#permit_autoloading_before-configuration)
|
85
|
+
option, which will effectively disable the gem's auto-loading prevention for
|
86
|
+
all migrations prior to a specified time
|
87
|
+
|
88
|
+
## Configuration
|
89
|
+
|
90
|
+
To configure the gem, call `GoodMigrations.config` at some point as Rails is
|
91
|
+
loading (a good idea would be an initializer like
|
92
|
+
`config/initializers/good_migrations.rb`)
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
GoodMigrations.config do |config|
|
96
|
+
# Setting `permit_autoloading_before` will DISABLE good_migrations for
|
97
|
+
# any migrations before the given time. Don't set this unless you need to!
|
98
|
+
#
|
99
|
+
# Accepts parseable time strings as well as `Date` & `Time` objects
|
100
|
+
# config.permit_autoloading_before = "20140728132502"
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
## Working around good_migrations
|
64
105
|
|
65
|
-
|
66
|
-
|
106
|
+
The gem only prevents auto-loading, so you can always can explicitly `require`
|
107
|
+
the app code that you need in your migration.
|
67
108
|
|
68
|
-
|
69
|
-
|
70
|
-
3. Remove the gem from your project
|
109
|
+
If needed, it is possible to run a command with `good_migrations` disabled by
|
110
|
+
running the command with the env var `GOOD_MIGRATIONS=skip`.
|
71
111
|
|
72
112
|
## Acknowledgements
|
73
113
|
|
74
114
|
Credit for figuring out where to hook into the ActiveSupport autoloader goes
|
75
115
|
to [@tenderlove](https://github.com/tenderlove) for [this
|
76
|
-
gist](https://gist.github.com/tenderlove/44447d1b1e466a28eb3f).
|
116
|
+
gist](https://gist.github.com/tenderlove/44447d1b1e466a28eb3f). And thanks to
|
117
|
+
[@fxn](https://github.com/fxn) for implementing the hook necessary for zeitwerk
|
118
|
+
support to be possible.
|
77
119
|
|
78
120
|
## Caveats
|
79
121
|
|
80
|
-
Because this gem works by
|
81
|
-
|
82
|
-
|
122
|
+
Because this gem works by augmenting the auto-loader, it will not work if your
|
123
|
+
Rails environment (development, by default) is configured to eager load your
|
124
|
+
application's classes (see:
|
83
125
|
[config.eager_load](http://edgeguides.rubyonrails.org/configuring.html#rails-general-configuration)).
|
data/example/Gemfile
CHANGED
data/example/config/boot.rb
CHANGED
@@ -0,0 +1,7 @@
|
|
1
|
+
GoodMigrations.config do |config|
|
2
|
+
# Setting `permit_autoloading_before` will DISABLE good_migrations for
|
3
|
+
# any migrations before the given time. Don't set this unless you need to!
|
4
|
+
#
|
5
|
+
# Accepts parseable time strings as well as `Date` & `Time` objects
|
6
|
+
config.permit_autoloading_before = ENV["PERMIT_AUTOLOADING_BEFORE"]
|
7
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module GoodMigrations
|
2
|
+
def self.config(&blk)
|
3
|
+
@configuration ||= Configuration.new
|
4
|
+
|
5
|
+
@configuration.tap do |config|
|
6
|
+
blk&.call(config)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Configuration
|
11
|
+
# Migrations with timestamps (the numbers at the beginning of the file name) from
|
12
|
+
# before this configured time will be allowed to perform autoloading, bypassing the
|
13
|
+
# mechanism of this gem. Accepts:
|
14
|
+
# nil (default): never permit autoload
|
15
|
+
# String accepted by `Time.parse`, such as: 20211103150610 or 20211103_150610
|
16
|
+
# object responding to `to_time`, such as Date and Time
|
17
|
+
attr_reader :permit_autoloading_before
|
18
|
+
def permit_autoloading_before=(value)
|
19
|
+
case value
|
20
|
+
when nil
|
21
|
+
# Stay nil
|
22
|
+
when String
|
23
|
+
value = Time.parse(value)
|
24
|
+
else
|
25
|
+
if value.respond_to?(:to_time)
|
26
|
+
value = value.to_time
|
27
|
+
else
|
28
|
+
raise "Received an invalid value for permit_autoloading_before: #{value.inspect}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
@permit_autoloading_before = value
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@permit_autoloading_before = nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module GoodMigrations
|
2
|
+
class MigrationDetails
|
3
|
+
attr_reader :path
|
4
|
+
def initialize(path)
|
5
|
+
@path = path
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.currently_executing
|
9
|
+
migrate_dir_path = Rails.root.join("db/migrate/").to_s
|
10
|
+
|
11
|
+
loc = caller.detect { |loc| loc.start_with?(migrate_dir_path) }
|
12
|
+
return if loc.nil?
|
13
|
+
new(loc.partition(":").first)
|
14
|
+
end
|
15
|
+
|
16
|
+
def associated_time
|
17
|
+
timestamp_string = File.basename(@path).partition("_").first
|
18
|
+
return if timestamp_string.size != 14
|
19
|
+
Time.parse(timestamp_string)
|
20
|
+
end
|
21
|
+
|
22
|
+
def considered_before?(time)
|
23
|
+
return false if time.nil?
|
24
|
+
my_time = associated_time
|
25
|
+
return false if my_time.nil?
|
26
|
+
my_time < time
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -5,11 +5,16 @@ module GoodMigrations
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def initialize
|
8
|
+
@permits_autoload = PermitsAutoload.new
|
9
|
+
@raises_load_error = RaisesLoadError.new
|
10
|
+
|
8
11
|
@disabled = false
|
9
12
|
end
|
10
13
|
|
11
|
-
def
|
12
|
-
@disabled
|
14
|
+
def prevent_autoload_if_necessary!(path)
|
15
|
+
return if @disabled || @permits_autoload.permit?(path)
|
16
|
+
|
17
|
+
@raises_load_error.raise!(path)
|
13
18
|
end
|
14
19
|
|
15
20
|
def patch!
|
@@ -20,14 +25,11 @@ module GoodMigrations
|
|
20
25
|
@disabled = false
|
21
26
|
Rails.autoloaders.each do |loader|
|
22
27
|
loader.on_load do |_, _, path|
|
23
|
-
|
24
|
-
!GoodMigrations::PatchesAutoloader.instance.disabled?
|
25
|
-
GoodMigrations::PreventsAppLoad.prevent_load!(path)
|
26
|
-
end
|
28
|
+
GoodMigrations::PatchesAutoloader.instance.prevent_autoload_if_necessary!(path)
|
27
29
|
end
|
28
30
|
end
|
29
31
|
else
|
30
|
-
warn
|
32
|
+
warn <<-UNSUPPORTED.strip_heredoc
|
31
33
|
WARNING: good_migrations is unable to ensure that your migrations are
|
32
34
|
not inadvertently loading application code, because your application
|
33
35
|
uses the zeitwerk autoloader (`config.autoloader = :zeitwerk`), but
|
@@ -44,12 +46,8 @@ module GoodMigrations
|
|
44
46
|
ActiveSupport::Dependencies.class_eval do
|
45
47
|
extend Module.new {
|
46
48
|
def load_file(path, const_paths = loadable_constants_for_path(path))
|
47
|
-
|
48
|
-
|
49
|
-
GoodMigrations::PreventsAppLoad.prevent_load!(path)
|
50
|
-
else
|
51
|
-
super
|
52
|
-
end
|
49
|
+
GoodMigrations::PatchesAutoloader.instance.prevent_autoload_if_necessary!(path)
|
50
|
+
super
|
53
51
|
end
|
54
52
|
}
|
55
53
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module GoodMigrations
|
2
|
+
class PermitsAutoload
|
3
|
+
def permit?(path)
|
4
|
+
!app_path?(path) || permit_autoloading_based_on_migration_time?
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def permit_autoloading_based_on_migration_time?
|
10
|
+
permit_before_date = GoodMigrations.config.permit_autoloading_before
|
11
|
+
migration_details = GoodMigrations::MigrationDetails.currently_executing
|
12
|
+
migration_details.considered_before?(permit_before_date)
|
13
|
+
end
|
14
|
+
|
15
|
+
def app_path?(path)
|
16
|
+
path.starts_with? File.join(Rails.application.root, "app")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,11 +1,7 @@
|
|
1
1
|
module GoodMigrations
|
2
|
-
class
|
3
|
-
def
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
def self.prevent_load!(path)
|
8
|
-
raise GoodMigrations::LoadError, <<~ERROR
|
2
|
+
class RaisesLoadError
|
3
|
+
def raise!(path)
|
4
|
+
raise GoodMigrations::LoadError, <<-ERROR.strip_heredoc
|
9
5
|
Rails attempted to auto-load:
|
10
6
|
|
11
7
|
#{path}
|
data/lib/good_migrations.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
-
require "
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
require "time"
|
2
|
+
|
3
|
+
require_relative "good_migrations/version"
|
4
|
+
require_relative "good_migrations/load_error"
|
5
|
+
require_relative "good_migrations/migration_details"
|
6
|
+
require_relative "good_migrations/configuration"
|
7
|
+
require_relative "good_migrations/patches_autoloader"
|
8
|
+
require_relative "good_migrations/permits_autoload"
|
9
|
+
require_relative "good_migrations/raises_load_error"
|
10
|
+
require_relative "good_migrations/railtie" if defined?(Rails)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: good_migrations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Searls
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2021-
|
12
|
+
date: 2021-11-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: railties
|
@@ -136,6 +136,7 @@ files:
|
|
136
136
|
- example/app/controllers/application_controller.rb
|
137
137
|
- example/app/helpers/application_helper.rb
|
138
138
|
- example/app/models/pant.rb
|
139
|
+
- example/app/models/shirt.rb
|
139
140
|
- example/app/views/layouts/application.html.erb
|
140
141
|
- example/bin/rails
|
141
142
|
- example/bin/rake
|
@@ -148,6 +149,7 @@ files:
|
|
148
149
|
- example/config/environments/production.rb
|
149
150
|
- example/config/environments/test.rb
|
150
151
|
- example/config/initializers/backtrace_silencers.rb
|
152
|
+
- example/config/initializers/good_migrations.rb
|
151
153
|
- example/config/initializers/inflections.rb
|
152
154
|
- example/config/initializers/mime_types.rb
|
153
155
|
- example/config/initializers/secret_token.rb
|
@@ -157,6 +159,8 @@ files:
|
|
157
159
|
- example/db/migrate/20160202162849_create_pants.rb
|
158
160
|
- example/db/migrate/20160202163803_change_pants.rb
|
159
161
|
- example/db/migrate/20160202182520_change_pants_dangerously.rb
|
162
|
+
- example/db/migrate/20170101150000_create_shirts.rb
|
163
|
+
- example/db/migrate/20170102150000_change_shirts_dangerously.rb
|
160
164
|
- example/db/seeds.rb
|
161
165
|
- example/doc/README_FOR_APP
|
162
166
|
- example/lib/tasks/.gitkeep
|
@@ -181,10 +185,13 @@ files:
|
|
181
185
|
- example/vendor/plugins/.gitkeep
|
182
186
|
- good_migrations.gemspec
|
183
187
|
- lib/good_migrations.rb
|
188
|
+
- lib/good_migrations/configuration.rb
|
184
189
|
- lib/good_migrations/load_error.rb
|
190
|
+
- lib/good_migrations/migration_details.rb
|
185
191
|
- lib/good_migrations/patches_autoloader.rb
|
186
|
-
- lib/good_migrations/
|
192
|
+
- lib/good_migrations/permits_autoload.rb
|
187
193
|
- lib/good_migrations/railtie.rb
|
194
|
+
- lib/good_migrations/raises_load_error.rb
|
188
195
|
- lib/good_migrations/version.rb
|
189
196
|
- tasks/good_migrations.rake
|
190
197
|
homepage: https://github.com/testdouble/good-migrations
|
@@ -206,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
206
213
|
- !ruby/object:Gem::Version
|
207
214
|
version: '0'
|
208
215
|
requirements: []
|
209
|
-
rubygems_version: 3.2.
|
216
|
+
rubygems_version: 3.2.22
|
210
217
|
signing_key:
|
211
218
|
specification_version: 4
|
212
219
|
summary: Prevents Rails from auto-loading app code in database migrations
|