I have a rails app that I'm moving to another server and I figure I should use db:schema:load to create the mysql database because it's recommended. My problem is that I'm using capistrano to deploy and it seems to be defaulting to rake db:migrate instead. Is there a way to change this or is capistrano using db:migrate for a good reason?
So schema:load takes the currently configured schema, derives the associated queries to match, and runs them all in one go. It's kind of a one-and-done situation. As you've seen, migrations make changes step-by-step.
Unlike rake db:migrate that runs migrations that have not run yet, rake db:schema:load loads the schema that is already generated in db/schema. rb into the database. Always use this command when: You run the application for the first time.
DB migration is moving data from one or more source platforms to another target database. There are several reasons for migrating from one database to another. For example, a business might want to save resources by switching to a cloud-based database.
The schema. rb serves mainly two purposes: It documents the final current state of the database schema. Often, especially when you have more than a couple of migrations, it's hard to deduce the schema just from the migrations alone. With a present schema.
I find that my own migrations eventually do some shuffling of data (suppose I combine first_name and last_name columns into a full_name column, for instance). As soon as I do any of this, I start using ActiveRecord to sift through database records, and your models eventually make assumptions about certain columns. My "Person" table, for instance, was later given a "position" column by which people are sorted. Earlier migrations now fail to select data, because the "position" column doesn't exist yet.
In conclusion, I believe deploy:cold
should use db:schema:load
instead of db:migrate
. I solved this problem by changing the middle step which Capistrano performs on a cold deploy. For Capistrano v2.5.9, the default task in the library code looks like this.
namespace :deploy do ... task :cold do update migrate # This step performs `rake db:migrate`. start end ... end
I overrode the task in my deploy.rb
as follows.
namespace :deploy do task :cold do # Overriding the default deploy:cold update load_schema # My own step, replacing migrations. start end task :load_schema, :roles => :app do run "cd #{current_path}; rake db:schema:load" end end
Climbing up on the shoulders of Andres Jaan Tack, Adam Spiers, and Kamiel Wanrooij, I've built the following task to overwrite deploy:cold.
task :cold do transaction do update setup_db #replacing migrate in original start end end task :setup_db, :roles => :app do raise RuntimeError.new('db:setup aborted!') unless Capistrano::CLI.ui.ask("About to `rake db:setup`. Are you sure to wipe the entire database (anything other than 'yes' aborts):") == 'yes' run "cd #{current_path}; bundle exec rake db:setup RAILS_ENV=#{rails_env}" end
My enhancements here are...
transaction do
, so that Capistrano will do a proper rollback after aborting.db:setup
instead of db:schema:load
, so that if the database doesn't already exist, it will be created before loading the schema.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With