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
In addition to running a migration in a different environment, I also want the schemas in separate files. You can do this from the command line:
RAILS_ENV=quiz_development SCHEMA=db/schema_quiz_development.rb rake db:migrate
But I like the custom rake task approach so I can type this instead:
rake db:with[quiz_development, db:migrate]
Here's the rake task:
namespace :db do
desc "Run :task against :database"
task :with, [:database,:task] => [:environment] do |t, args|
puts "Applying #{args.task} to #{args.database}"
ENV['SCHEMA'] ||= "#{Rails.root}/db/schema_#{args.database}.rb"
begin
oldRailsEnv = Rails.env
Rails.env = args.database
ActiveRecord::Base.establish_connection(args.database)
Rake::Task[args.task].invoke
ensure
Rails.env = oldRailsEnv
end
end
end
if you want to display the wordpress post to your rails website and you don't want to use mult-magic connection gem. you can use the below code in order to get the data from wordpress blog.
class Article < ActiveRecord::Base
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "localhost",
:username => "root",
:database => "blog"
)
self.table_name = 'wp_posts'
def self.get_post_data()
query = "select name from testing"
tst = connection.select_all(query)
tst[0].fetch('name')
end
end
Based on @TheDeadSerious's answer:
module ActiveRecord::ConnectionSwitch
def on_connection(connection_spec_name)
raise ArgumentError, "No connection specification name specified. It should be a valid spec from database.yml" unless connection_spec_name
ActiveRecord::Base.establish_connection(connection_spec_name)
yield
ensure
ActiveRecord::Base.establish_connection(Rails.env)
end
end
ActiveRecord.send :extend, ActiveRecord::ConnectionSwitch
Usage:
ActiveRecord.on_connection "sdmstore_#{Rails.env}" do
Widget.delete_all
end
I recently struggled with the same problem. The goal was to split off a histories table to a different database since it was already so large and still growing very quickly.
I started trying to resolve it by doing ActiveRecord::Base.establish_connection(:history_database)
, but could not get any variations of that way to work without the connection being closed. Then finally I discovered the solution below.
In the History model after making this change:
class History < ActiveRecord::Base
# Directs queries to a database specifically for History
establish_connection :history_database
...
end
I was able to do this in the migration and it worked perfectly:
class CreateHistoriesTableInHistoryDatabase < ActiveRecord::Migration
def up
History.connection.create_table :histories do |t|
...
end
end
def down
History.connection.drop_table :histories
end
end
This will create the table in a different database, yet modify the schema_migrations table in the original database so the migration does not run again.
I got this working by creating separate connector classes for different databases and using them in the migrations.
class AddExampleToTest < ActiveRecord::Migration
def connection
@connection = OtherDatabaseConnector.establish_connection("sdmstore_#{Rails.env}").connection
end
def up
add_column :test, :example, :boolean, :default => true
@connection = MainDatabaseConnector.establish_connection("#{Rails.env}").connection
end
def down
remove_column :test, :example
@connection = MainDatabaseConnector.establish_connection("#{Rails.env}").connection
end
end
We can define these connector classes in initializers.
class MainDatabaseConnector < ActiveRecord::Base
end
class OtherDatabaseConnector < ActiveRecord::Base
end
ActiveRecord::Base keeps a connection pool that is a hash indexed by the class. Read more here. So using separate classes for separate connections protects us from the closed connection error.
Also, using up
and down
instead of change
allows us to rollback the migration without any issue. Still haven't figured out the reason for this.
Following on from @Bryan Larsen, if you're using an abstract Class to attach a series of models to a different database, and would like to migrate schemas on them, then you can do this:
class CreatePosts < ActiveRecord::Migration
def connection
Post.connection
end
def up
...
end
end
with a model set up something like:
class Post < ReferenceData
end
and
class ReferenceData < ActiveRecord::Base
self.abstract_class = true
establish_connection "reference_data_#{Rails.env}"
end