21

I dont want Rails 3 to generate my schema every time I do migration. How to properly disable it?

Thanks

lzap
  • 16,417
  • 12
  • 71
  • 108

6 Answers6

76

For anyone who is still looking for a way to disable the db dump after migration a configuration is now available in rails 4 which can be set to false like this:

config.active_record.dump_schema_after_migration = false

will prevent it. The configuration has been added in this change - https://github.com/rails/rails/pull/13948

ZX12R
  • 4,760
  • 8
  • 38
  • 53
  • 1
    This is the real answer. The rest are really just hacks. Thanks, you saved me a lot of pain. – jmervine May 20 '16 at 15:32
  • 2
    Please note that this works on version 4 and above. David Waller's answer works for earlier versions (which i have used in some legacy apps) – ZX12R May 20 '16 at 17:03
  • Now that rails supports multiple databases it would be great if this were configurable on a db by db basis. I'm having to use the previous hacks like David Waller's answer to get around dumping a schema for a db which I only have read access to in production (but need write access to locally). Every time I run migrations for my main db it dumps the schema for my other one co-contributorsa are always having to git checkout the file. – davidpm4 Apr 12 '20 at 01:55
9

Create an application specific task (as Alex Kaushovik suggested) like so...

Create a file lib\tasks\db_schema_override (actual name doesn't matter, you need a .rake file in lib\tasks) with contents as below (credit to Matthew Bass for remove_task)

Rake::TaskManager.class_eval do
  def remove_task(task_name)
    @tasks.delete(task_name.to_s)
  end
end

Rake.application.remove_task('db:schema:dump')
namespace :db do
  namespace :schema do
    task :dump do
      # Overridden to do nothing
    end
  end
end
reto
  • 16,189
  • 7
  • 53
  • 67
David Waller
  • 3,057
  • 4
  • 27
  • 28
  • 1
    I've found it useful to only perform the override for non-development environments. Like this for Rails 2.x: `if RAILS_ENV != 'development'` – Mark Eric Oct 04 '11 at 18:33
  • The problem with this approach is that it leaves you without the ability to run db:schema:dump at all. While I don't want it to run automatically, I do want to invoke it manually on occasion. See my answer elsewhere on this page. – KenB Aug 21 '13 at 17:38
1

A modification based on David Waller's answer that retains the ability to run db:schema:dump manually. Covers all tasks where schema dumping is automatically invoked. Based on rails 3.2.14 versions of the relevant tasks - when you change rails versions, you'll want to ensure that the task definitions are still valid.

Seriously, there should be a config option to disable automatic schema dumps.

Rake::TaskManager.class_eval do
  def remove_task(task_name)
    @tasks.delete(task_name.to_s)
  end

  Rake.application.remove_task("db:migrate")
  Rake.application.remove_task("db:rollback")
  Rake.application.remove_task("db:forward")
  Rake.application.remove_task("db:migrate:up")
  Rake.application.remove_task("db:migrate:down")

end

namespace :db do

  desc "Migrate the database (options: VERSION=x, VERBOSE=false)."
  task :migrate => [:environment, :load_config] do
    ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
    ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) do |migration|
      ENV["SCOPE"].blank? || (ENV["SCOPE"] == migration.scope)
    end
    # db_namespace['_dump'].invoke
  end

  desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
  task :rollback => [:environment, :load_config] do
    step = ENV['STEP'] ? ENV['STEP'].to_i : 1
    ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step)
    # db_namespace['_dump'].invoke
  end

  # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
  task :forward => [:environment, :load_config] do
    step = ENV['STEP'] ? ENV['STEP'].to_i : 1
    ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_paths, step)
    # db_namespace['_dump'].invoke
  end

  namespace :migrate do

    # desc 'Runs the "up" for a given migration VERSION.'
    task :up => [:environment, :load_config] do
      version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
      raise 'VERSION is required' unless version
      ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_paths, version)
      # db_namespace['_dump'].invoke
    end

    # desc 'Runs the "down" for a given migration VERSION.'
    task :down => [:environment, :load_config] do
      version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
      raise 'VERSION is required' unless version
      ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_paths, version)
      # db_namespace['_dump'].invoke
    end

  end

end
KenB
  • 6,587
  • 2
  • 35
  • 31
0

The default behavior of Active Record is to dump the schema, but it only does it if the schema dump format is set to ruby (the default).

You can disable the schema dump after migrations by setting the schema format to sql. You can safely reverse it to ruby after the migration finishes without consequences.

You can do it in this way:

1) If you have a line like this one setting explicitly the schema to ruby:

config.active_record.schema_format = :ruby

(it could be inside config/application.rb, on config/environment or in the specific environment you are running the migration in).

Then comment it out:

#config.active_record.schema_format = :ruby

2) Then add a line to set the schema format to SQL, either in the environment you are using, or at config/application.rb, as follows:

config.active_record.schema_format = :sql
CCD
  • 336
  • 3
  • 3
0

Rather than overriding the db:migrate behavior (which is obviously necessary when you're building the migration in development, but unnecessary when deploying) I would suggest creating a separate task like:

# http://stackoverflow.com/questions/13646840/how-to-make-rake-dbmigrate-generate-schema-rb-when-using-sql-schema-format
namespace :db do
  desc "Migrate the database, without dumping the schema.rb"
  task :deploy => :environment do
    ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
    ActiveRecord::Migrator.migrate("db/migrate/", nil)
  end
end

Then during your deployments you can simply do

rake db:deploy
Luke Schlather
  • 367
  • 2
  • 13
0

I've tested the following - it works:

You could modify the file "databases.rake" inside of the Rails gem's lib/tasks folder on your server(s). Comment out lines with the following code:

Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby

By default on Ubuntu (and Ubuntu server) it is here: /var/lib/gems/1.8/gems/rails-x.x.x/lib/tasks/databases.rake.

Tested with Rails 2.3.11, but I'm pretty sure it'll work with Rails 3.x.x too.

Another possible solution (didn't test):

You wouldn't have to modify Rails files, just your application.

A rails plugin called "override_rake_task" could be used to override Rake task "db:schema:dump" which is defined inside if Rails gem.

Apparently if you are not using this plugin and if you define a task in your rails application with the same name, rake would execute both tasks: the default and yours.

Alex Kovshovik
  • 4,085
  • 4
  • 35
  • 36
  • 3
    Changing another gems source is very bad idea. If you must you can checkout the source unter vendor/rails and add it to your source repo. – reto Dec 13 '11 at 11:17
  • 2
    Agree on that one. The problem with changed gems is that when you'll need to update them eventually - you'll have to apply those patches again, possible in different places. – Alex Kovshovik Dec 14 '11 at 01:25