rake db:migrate should not invoke dump task in production environment

Currently the db:migrate rake task runs dump at the end which dumps the database structure to schema.rb / structure.sql. This will be useful in development environment but I can’t see a reason why this should run in production environment. Removing this step in production would make deployments faster, I believe. Do others think that this should be fixed ?

Rails code that invokes dump

I agree. Just yesterday, I wrote a separate task that only did migrations for deploy.

I occasionally run diff’s on the production schema.rb or structure.sql against what is in git to be sure development environments are staying in sync with production.

Seth, please correct me if I'm mistaken. Since the branch that gets
deployed in production already has a structure.sql , we can always compare
that with the development branches. What's the need for having a migration
task prepare structure.sql in a production environment ?

Sorry if I wasn't clear before. Changes to structure.sql are only ever
committed in development. When production runs a db:migrate it spits out a
new version of structrue.sql. If I run a `git status` on production and
see changes to structure.sql I know something is out of sync with the SCM
deployed code and production. Ideally this would never happen, but I've
helped out on projects where legacy columns were on production tables that
were not reflected in the structure.sql file.

Does that clarify my use case?

Seth

Adding support for this in principle makes sense to me. Since we want the
file to be generated in some environments an not in others, a generated
flag would probably make sense. A flag could also support the use case
explained by Seth, since he would just toggle it in
config/environments/production.rb (say).

I agree, that’s what I had in mind too . How about a config named “generate_schema_after_migration” which holds true/false. It could be true by default, and you can override the default behavior by setting it to false in config/environments/production.rb. I am ready to work on this if I get a green light.

Sounds good to me. The flag would be true by default for backwards compat, but newly generated apps would have it generated in the environment config files.

For new apps the generated flag assignment would assign to false in production.rb.

The value for the test environment is doubtful, but I think it is better not to generate the flag in test.rb. The reason is that generating the schema after running migrations is a responsibility of the development environment. In particular, you are not supposed to run migrations with RAILS_ENV=test. Therefore, having a flag related to migrations written in test.rb could send a confusing message in my view. If the test environment has nothing to do with migrations, why do I need to say anything about them in its config?

So, I believe for the test environment with can leave it at the implicit true default.

Xavier, you wrote that we are not supposed to run migrations with RAILS_ENV=test, but the Rails itself occasionally prompts us to do it.

For example, when I run rspec command having pending migrations on test environment, the Rails emits the following message:

Migrations are pending. To resolve this issue, run:

bin/rake db:migrate RAILS_ENV=test

This message is embedded in /activerecord/lib/active_record/migration.rb.

I am not sure if this message is a correct instruction or not, though.

Xavier, you wrote that we are not supposed to run migrations with

RAILS_ENV=test, but the Rails itself occasionally prompts us to do it.

For example, when I run rspec command having pending migrations on test
environment, the Rails emits the following message:

> Migrations are pending. To resolve this issue, run:
>
> bin/rake db:migrate RAILS_ENV=test

This message is embedded in /activerecord/lib/active_record/migration.rb.

I am not sure if this message is a correct instruction or not, though.

I believe that message is not consistent with the golden path.

The big guidelines here are:

* Migrations run to evolve the schema. As a side-effect, running them
generates db/schema.(rb|sql).

* The test environment should always start afresh, the test database is
considered to be transient by design, gets trashed and rebuilt, and
therefore has no evolutive maintenance.

* Because of that, the test environment setup is designed around
db/schema.(rb|sql), not around migrations. You need to get
db/schema.(rb|sql) right *first*, then run the suite.

* The interface to that workflow is encoded via rake tasks. The test
environment setup loads the current schema. If you go always through rake
tasks everything works out of the box as long as the schema is in sync with
migrations. If it isn't, you need to run migrations in the development
environment to update the schema (and to have an up to date schema in the
development database of course).

* If for some reason you prefer not to go through rake tasks for running
tests, that's a little deviation from the point of view of the Rails
interface, but the point closer to the golden path is to load the schema by
hand (db:schema:load), not to run migrations in the test environment.

So, yeah, from my perspective that message is not pointing in the right
direction.

I agree, test environment should not evolve the schema, instead depend on an existing schema. So I think it makes sense not to generate schema if at all I choose to run migrations in the test environment.

I’ve sent a PR for this. Please give it a look : https://github.com/rails/rails/pull/13948

For the archives, this has been merged

    https://github.com/rails/rails/compare/7f648bc70e76...c0fb8d0b9c4d

Thanks Emil!