如何在Heroku中为一个rails 3.1 app使用多个数据库?

gen*_*abs 13 mysql heroku ruby-on-rails-3.1

My Rails 3.1应用程序连接到2个数据库,一个是默认值,另一个是Amazon RDS MYSQL实例.

当前的database.yml包含两个生产数据库连接.需要从第二个数据库中提取的模型只需使用

establish_connection "production_on_amazon"
Run Code Online (Sandbox Code Playgroud)

不幸的是,Heroku会覆盖你的database.yml,而且似乎只包含一个数据库连接.有谁知道如何添加或配置我的第二个?

运行"heroku config"我可以看到列出了2个DB,但似乎无法配置连接到两者.也许以某种方式将我的默认值设置为Heroku上的SHARED_DATABASE_URL数据库,并将备用设置为指向Amazon的DATABASE_URL ...

Wat*_*Box 7

处理以前的响应,但在配置中结合了一些Rails 3的优点并简化了解析...

# config/application.rb
module MyApp
  class Application < Rails::Application
    ... other configs

    config.secondary_database_url = ENV['SECONDARY_DB_URL']
  end
end
Run Code Online (Sandbox Code Playgroud)

我们可能希望在开发/测试中覆盖它

# config/environments/development.rb

module MyApp
  class Application < Rails::Application
    ... other configs

    config.secondary_database_url = 'SOME_CONNECTION_STRING'
  end
end    
Run Code Online (Sandbox Code Playgroud)

现在要设置类,我们将继承我们的模型......

# 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
Run Code Online (Sandbox Code Playgroud)


gen*_*abs 2

关于尼尔的回答,这是一种方法。不是开箱即用的解决方案,但可能会给您一个想法... /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
Run Code Online (Sandbox Code Playgroud)

所以你的模型应该只扩展 ActiveRecord::Shard 而不是 Base