My Rails 3.1 application connects to 2 databases, one is the default, the other is an Amazon RDS MYSQL instance.
The current database.yml contains two production database connections. The models that need to pull from the second database simply use
establish_connection "production_on_amazon"
Unfortunately Heroku overwrites your database.yml, and only seems to inlcude one database connection. Does anyone know how I can add or configure my second?
Running "heroku config" I can see there are 2 DB's listed but cant seem to configure to connect to both. Perhaps somehow set my default to the SHARED_DATABASE_URL db on Heroku and set the alternate to the DATABASE_URL which points to Amazon...
Working off of the previous responses, but incorporating some Rails 3 advantages with the configuration and simplifying the parsing...
# config/application.rb
module MyApp
class Application < Rails::Application
... other configs
config.secondary_database_url = ENV['SECONDARY_DB_URL']
end
end
We may want to override this in development / test
# config/environments/development.rb
module MyApp
class Application < Rails::Application
... other configs
config.secondary_database_url = 'SOME_CONNECTION_STRING'
end
end
Now to setup the class we'll have our models inherit from...
# lib/active_record/secondary.rb
module ActiveRecord
class Secondary < ActiveRecord::Base
self.abstract_class = true
# prior to AR 3.2.1
url = URI.parse( MyApp::Application.config.secondary_database_url )
establish_connection(
:adapter => 'mysql',
:host => url.host,
:username => url.userinfo.split(':')[0],
:password => url.userinfo.split(':')[1],
:database => url.path[1..-1],
:port => url.port || 3306
)
# as of AR 3.2.1
establish_connection(MyApp::Application.config.secondary_database_url)
end
class SecondaryMigration < ActiveRecord::Migration
def connection
ActiveRecord::Secondary.connection
end
end
end
Heroku will always connect your app to the production DB that they create for you. If you want to make an additional connection you'll need to do this in your code manually, and create a ENV var that the code can use as a connection string.
Anything in the production segment of database.yml is binned by Heroku and replaced.
Regarding Neil's answer, here is a way to do it. Not an out-of-box solution, but might give you an idea... /lib/active_record_extensions.rb
module ActiveRecordExtensions
class Shard < ActiveRecord::Base
#need to switch to the shard database connection from heroku config
primary_database_url = ENV['PRIMARY_DATABASE_URL']
if(!primary_database_url.nil?)
parsed_connection_string = primary_database_url.split("://")
adapter = parsed_connection_string[0]
parsed_connection_string = parsed_connection_string[1].split(":")
username = parsed_connection_string[0]
parsed_connection_string = parsed_connection_string[1].split("@")
password = parsed_connection_string[0]
parsed_connection_string = parsed_connection_string[1].split("/")
host = parsed_connection_string[0]
database = parsed_connection_string[1]
establish_connection(
:adapter => adapter,
:host => host,
:username => username,
:password => password,
:database => database,
:port => 3306,
:pool => 5,
:timeout => 5000
)
else
self.establish_connection "shard_#{Rails.env}"
end
end
class ShardMigration < ActiveRecord::Migration
def connection
ActiveRecord::Shard.connection
end
end
end
So your model should just extend ActiveRecord::Shard instead of Base
来源:https://stackoverflow.com/questions/7677544/how-to-use-multiple-databases-for-one-rails-3-1-app-in-heroku