如何用rake tasks 生成migration对应的sql

how-to-use-rake-tasks-to-generate-migration-sql

Rakefile文件里有load_tasks的方法

http://api.rubyonrails.org/

Load Rake, railties tasks and invoke the registered hooks. Check Rails::Railtie.rake_tasks for more info.

Source: hide | on GitHub

# File railties/lib/rails/engine.rb, line 451
def load_tasks(app=self)
  require "rake"
  run_tasks_blocks(app)
  self
end
rake_tasks(&block) 
If you try to define a set of rake tasks on the instance, 
these will get passed up to the rake tasks defined on the application's class. Source: hide | on GitHub # File railties/lib/rails/application.rb, line 270 def rake_tasks(&block) self.class.rake_tasks(&block) end

相关文档

http://guides.rubyonrails.org/command_line.html

https://github.com/ruby/rake

http://eewang.github.io/blog/2013/07/29/how-to-use-rake-tasks-to-generate-migration-sql/

开始写代码了。

在lib/tasks/文件夹新建migrate.rake

# 根据下面的博客做了一点点修改
# http://eewang.github.io/blog/2013/07/29/how-to-use-rake-tasks-to-generate-migration-sql/
namespace :db do               
  [ :migrate, :rollback ].each do |n|
    namespace n do |migration_task| 
      # original_task = migration_task.instance_variable_get("@scope").join ":"

      [:with_sql, :to_sql ].each do |t|
        desc "Run migration, and generated SQL" if t == :with_sql
        desc "Generate migration SQL" if t == :to_sql
        task t => :environment do |sql_task| 
          original_task = sql_task.name.sub(":#{t}", '')

          case original_task   
          when 'db:migrate'    
            filename = 'upgrade.sql'        
          when 'db:rollback'   
            filename = 'rollback.sql'       
          else                 
            raise "unkown migration type #{original_task}"
          end                  
  
          ActiveRecord::Base.connection.class.class_eval do
            # alias the adapter's execute for later use
            alias :old_execute :execute  

  
            SQL_FILENAME = filename         
            RUN_SQL = sql_task.name.ends_with?("with_sql")

            # define our own execute        
            def execute(sql, name = nil)    
              # check for some DDL and DML statements
              if /^(create|alter|drop|insert|delete|update)/i.match sql
                File.open(SQL_FILENAME, 'a') { |f| f.puts "#{sql};
" } 
                old_execute sql, name if RUN_SQL
              else
                # pass everything else to the aliased execute
                old_execute sql, name
              end
            end

          end

          # create or delete content of migration.sql
          File.open(SQL_FILENAME, 'w') { |f| f.puts "-- Script created @ #{Time.now}" }

          # invoke the normal migration procedure now
          Rake::Task[original_task].invoke

          puts "Ran #{original_task} and wrote sql to #{filename}"
        end
      end
    end
  end
end

这时候来执行$ rake -T db

可以看到新增的功能

rake db:create              # Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all t...
rake db:drop                # Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to dr...
rake db:fixtures:load       # Load fixtures into the current environment's database
rake db:migrate             # Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
rake db:migrate:status      # Display status of migrations
rake db:migrate:to_sql      # Generate migration SQL
rake db:migrate:with_sql    # Run migration, and generated SQL
rake db:rollback            # Rolls the schema back to the previous version (specify steps w/ STEP=n)
rake db:rollback:to_sql     # Generate migration SQL
rake db:rollback:with_sql   # Run migration, and generated SQL

$ mysqldump -uroot -p ott_remote_cms_development > back.sql

$ rake db:drop

$ rake db:create

$ rake db:migrate:with_sql

$ mysql -uroot -p ott_remote_cms_development < back.sql

$ cat upgrade.sql

把sql发给dba就可以了,确实太麻烦了。

原文地址:https://www.cnblogs.com/iwangzheng/p/5333474.html