【问题标题】:How to use multiple databases for one rails 3.1 app in Heroku?如何在 Heroku 中为一个 rails 3.1 应用程序使用多个数据库?
【发布时间】:2011-12-02 09:58:02
【问题描述】:

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

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

establish_connection "production_on_amazon"

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

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

【问题讨论】:

    标签: mysql ruby-on-rails-3.1 heroku


    【解决方案1】:

    Heroku 将始终将您的应用连接到他们为您创建的生产数据库。如果您想建立一个额外的连接,您需要在您的代码中手动执行此操作,并创建一个代码可以用作连接字符串的 ENV var。

    database.yml 的生产段中的任何内容都被 Heroku 分箱并替换。

    【讨论】:

    • 对于那些想知道他们如何做到这一点的人,我决定的方法是在 lib 文件夹中的一个模块中扩展 ActiveRecord::Base,然后在我的模型中扩展我的新类,这样我可以跨多种数据库分片是一种有点干的方式。
    【解决方案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
    

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

    【讨论】:

    • 您可以使用 Ruby 的 URI,而不是进行所有这些手动解析,例如:parsed_uri = URI(ENV['PRIMARY_DATABASE_URL'])
    【解决方案3】:

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

    # config/application.rb
    module MyApp
      class Application < Rails::Application
        ... other configs
    
        config.secondary_database_url = ENV['SECONDARY_DB_URL']
      end
    end
    

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

    # config/environments/development.rb
    
    module MyApp
      class Application < Rails::Application
        ... other configs
    
        config.secondary_database_url = 'SOME_CONNECTION_STRING'
      end
    end    
    

    现在来设置类,我们的模型继承自...

    # 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
    

    【讨论】:

    • 注意:从 3.2.1 开始,你根本不需要解析数据库 url。您可以直接将其传递给建立连接。 apidock.com/rails/v3.2.1/ActiveRecord/Base/establish_connection/…
    • 仅供参考,让 ActiveRecord::Secondary 从 ActiveRecord::Base 继承可能会导致问题:ActiveRecord::StatementInvalid: Could not find table 'secondaries'
    • @Ajedi32 如果您将抽象类设置为我忘记包含的 true,则不会
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2011-09-09
    • 1970-01-01
    • 2011-01-08
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多