{"id":13877949,"url":"https://github.com/testdouble/good-migrations","last_synced_at":"2025-07-16T14:30:36.148Z","repository":{"id":3801601,"uuid":"50945208","full_name":"testdouble/good-migrations","owner":"testdouble","description":"Prevent Rails from auto-loading app/ code when running database migrations","archived":false,"fork":false,"pushed_at":"2025-05-13T15:49:20.000Z","size":175,"stargazers_count":316,"open_issues_count":3,"forks_count":9,"subscribers_count":53,"default_branch":"main","last_synced_at":"2025-06-13T18:49:00.170Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/testdouble.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-02-02T19:15:35.000Z","updated_at":"2025-06-13T18:03:05.000Z","dependencies_parsed_at":"2025-05-13T16:40:01.680Z","dependency_job_id":"c872a071-b58c-45a0-bc34-758d17c8c1a3","html_url":"https://github.com/testdouble/good-migrations","commit_stats":{"total_commits":71,"total_committers":6,"mean_commits":"11.833333333333334","dds":0.2816901408450704,"last_synced_commit":"c059a8f0c9c8bd1349ef8e80af50deb2ac1d84e1"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/testdouble/good-migrations","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testdouble%2Fgood-migrations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testdouble%2Fgood-migrations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testdouble%2Fgood-migrations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testdouble%2Fgood-migrations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/testdouble","download_url":"https://codeload.github.com/testdouble/good-migrations/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testdouble%2Fgood-migrations/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265293375,"owners_count":23742285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-06T08:01:35.752Z","updated_at":"2025-07-16T14:30:35.419Z","avatar_url":"https://github.com/testdouble.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# good_migrations\n\nThis gem prevents Rails from auto-loading app code while it's running migrations,\npreventing the common mistake of referencing ActiveRecord models from migration\ncode.\n\n## Usage\n\nAdd `good_migrations` to your Gemfile:\n\n``` ruby\ngem 'good_migrations'\n```\n\nAnd you're done! That's it.\n\n## Prerequisites\n\nThis gem requires that your app uses either of these autoloader strategies:\n\n* The classic `ActiveSupport::Dependencies` autoloader (e.g. `config.autoloader\n  = :classic`), which is going away with Rails 7\n* **Version 2.5 or higher** of the Zeitwerk autoloader (e.g. `config.autoloader =\n  :zeitwerk`) If your app uses an earlier version of zeitwerk, you'll see a\n  warning every time `db:migrate` is run\n\n## Background\n\nOver the life of your [Ruby on Rails](http://rubyonrails.org) application, your\napp's models will change dramatically, but according to the [Rails\nguides](http://guides.rubyonrails.org/active_record_migrations.html#changing-existing-migrations), your migrations _shouldn't_:\n\n\u003e In general, editing existing migrations is not a good idea. You will be\ncreating extra work for yourself and your co-workers and cause major headaches\nif the existing version of the migration has already been run on production\nmachines. Instead, you should write a new migration that performs the changes you\nrequire.\n\nThat means that if your migrations reference the ActiveRecord model objects\nyou've defined in `app/models`, your old migrations are likely to break. That's\nnot good.\n\nBy adding this gem to your project's `Gemfile`, autoloading paths inside `'app/'`\nwhile running any of the `db:migrate` Rake tasks will raise an error, explaining\nthe dangers inherent.\n\nSome will reply, \"who cares if old migrations are broken? I can still run `rake\ndb:setup` because I have a `db/schema.rb` file\". The problem with this approach\nis that, so long as some migrations aren't runnable, the `db/schema.rb` can't\nbe regenerated from scratch and its veracity can no longer be trusted. In\npractice, we've seen numerous projects accumulate cruft in `db/schema.rb` as the\nresult of erroneous commits to work-in-progress migrations, leading to the\ndevelopment and test databases falling out of sync with production. That's not\ngood!\n\nFor more background, see the last section of this blog post on [healthy migration\nhabits](http://blog.testdouble.com/posts/2014-11-04-healthy-migration-habits.html)\n\n## Adding to an existing app\n\nIf you add `good_migrations` to an existing application **and** any of those\nmigrations relied on auto-loading code from `app/`, then you'll see errors\nraised whenever those migrations are run.\n\nYou have several options if this happens:\n\n* If you're confident that every long-lasting environment has run the latest\n  migrations, you could consider squashing your existing migrations into a\n  single migration file that reflects the current state of your schema. This is\n  a tricky procedure to pull off in complex apps, and can require extra\n  coordination in cases where a high number of contributors are working on the\n  application simultaneously. The\n  [squasher](https://github.com/jalkoby/squasher) gem may be able to help.\n* You can rewrite those past migrations to inline any application code inside\n  the migration's namespace. One way to do this is to run migrations until they\n  fail, check out the git ref of the failing migration so the codebase is\n  rewound to where it was at the time the migration was written, and finally\n  inline the necessary app code to get the migration passing before checking out\n  your primary branch. Rewriting any migration introduces risk of the resulting\n  schema diverging from production, so this requires significant care and\n  attention\n* If neither of the above options are feasible, you can configure the\n  `good_migrations` gem to ignore migrations prior to a specified date with the\n  [permit_autoloading_before](#permit_autoloading_before-configuration)\n  option, which will effectively disable the gem's auto-loading prevention for\n  all migrations prior to a specified time\n\n## Configuration\n\nTo configure the gem, call `GoodMigrations.config` at some point as Rails is\nloading (a good idea would be an initializer like\n`config/initializers/good_migrations.rb`)\n\n```ruby\nGoodMigrations.config do |config|\n  # Setting `permit_autoloading_before` will DISABLE good_migrations for\n  # any migrations before the given time. Don't set this unless you need to!\n  #\n  # Accepts parseable time strings as well as `Date` \u0026 `Time` objects\n  # config.permit_autoloading_before = \"20140728132502\"\nend\n```\n\n## Working around good_migrations\n\nThe gem only prevents auto-loading, so you can always can explicitly `require`\nthe app code that you need in your migration.\n\nIf needed, it is possible to run a command with `good_migrations` disabled by\nrunning the command with the env var `GOOD_MIGRATIONS=skip`.\n\n## Acknowledgements\n\nCredit for figuring out where to hook into the ActiveSupport autoloader goes\nto [@tenderlove](https://github.com/tenderlove) for [this\ngist](https://gist.github.com/tenderlove/44447d1b1e466a28eb3f). And thanks to\n[@fxn](https://github.com/fxn) for implementing the hook necessary for zeitwerk\nsupport to be possible.\n\n## Caveats\n\nBecause this gem works by augmenting the auto-loader, it will not work if your\nRails environment (development, by default) is configured to eager load your\napplication's classes (see:\n[config.eager_load](http://edgeguides.rubyonrails.org/configuring.html#rails-general-configuration)).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftestdouble%2Fgood-migrations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftestdouble%2Fgood-migrations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftestdouble%2Fgood-migrations/lists"}