Using Rails Migration on different database than standard “production” or “development”

前端 未结 20 1329
借酒劲吻你
借酒劲吻你 2020-11-29 18:18

I have a rails project running that defines the standard production:, :development and :test DB-connections in config/database.yml

In addition I have a quiz_developm

相关标签:
20条回答
  • 2020-11-29 18:55

    You can also move all your quiz_ related migrations into a separate subfolder in the db/ directory and then add rake tasks mirroring the regular migration functionality but that looks for the migrations in that subdirectory. Not super-elegant perhaps but it works. You can copy and paste the rake tasks already in rails and just modify them a bit.

    0 讨论(0)
  • 2020-11-29 18:56

    Hey I been digging into this for a few days and I ended up with this solution, just wanted to share it, it might help someone.

    Here the complete gist for it. https://gist.github.com/rafaelchiti/5575309 It has details ans explanation. But find below more details if you need them.

    The approach is based on adding a namespace to the already known rake tasks db:migrate, db:create, db:drop and perform those tasks with a different database. And then in adding a base active record (AR) class for connecting based on the configuration of the new database.yml file. This way you don't need to hack around the migrations with connection stuff and you get a clean directory structure.

    Your structure will end up like this

    config
      |- database.yml
      \- another_database.yml (using the same nomenclature of 'development', 'test', etc).
    
    db
      |- migrate (default migrate directory)
      |- schema.rb
      |- seed.rb
    
    another_db
      |- migrate (migrations for the second db)
      |- schema.rb (schema that will be auto generated for this db)
      |- seed.rb (seed file for the new db)
    

    Then in your code you can create a base class and read the config from this new database.yml file and connect to it only on the models that inherit from that AR base class. (example in the gist).

    Best!.

    0 讨论(0)
  • 2020-11-29 18:59

    There's a much easier answer. Add this to your migration:

    def connection
      ActiveRecord::Base.establish_connection("quiz_#{Rails.env}").connection
    end
    

    That's for Rails 3.1. For Rails 2.X or 3.0 it's a class function instead (eg def self.connection)

    0 讨论(0)
  • 2020-11-29 18:59
    module ActiveRecord::ConnectionSwitch
      def on_connection(options)
        raise ArgumentError, "Got nil object instead of db config options :(" if options.nil?
        ActiveRecord::Base.establish_connection(options)
        yield
      ensure
        ActiveRecord::Base.establish_connection ActiveRecord::Base.configurations[Rails.env]
      end
    end
    
    ActiveRecord.send :extend, ActiveRecord::ConnectionSwitch
    

    If you place this inside config/initializers/ you'll be able to do something like this:

    ActiveRecord.on_connection ActiveRecord::Base.configurations['production'] do
      Widget.delete_all
    end
    

    This will delete all widgets on the production db and make sure the connection to the current Rails env's db is re-established after that.

    If you just want to make it available in your migrations insead extend the ActiveRecord::Migration class.

    0 讨论(0)
  • 2020-11-29 19:02

    I've found a great clean way to do this:

    class CreateScores < ActiveRecord::Migration
    
      class ScoresDB < ActiveRecord::Base
        establish_connection("scores_#{Rails.env}")
      end
    
      def connection
        ScoresDB.connection
      end
    
      def up
        create_table :scores do |t|
          t.text :account_id
          t.text :offer
        end
      end
    
      def down
        drop_table :scores
      end
    end
    
    0 讨论(0)
  • 2020-11-29 19:03

    A bit late, but I was dealing with this problem today and I came up with this custom rake task:

    namespace :db do
      desc "Apply db tasks in custom databases, for example  rake db:alter[db:migrate,test-es] applies db:migrate on the database defined as test-es in databases.yml"
      task :alter, [:task,:database] => [:environment] do |t, args|
        require 'activerecord'
        puts "Applying #{args.task} on #{args.database}"
        ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[args.database])
        Rake::Task[args.task].invoke
      end
    end
    
    0 讨论(0)
提交回复
热议问题