5

Heroku でホストされている Rails アプリがあり、マーケティング担当者のためにいくつかの分析ページを設定する必要があります。これは、Herokuフォロー データベースの典型的なユース ケースのようです。

2 つのデータベースは同じモデル クラスを共有します。レプリケートされたデータベースに対してクエリを実行するアクションのみが必要です。

アプリでこの状況を処理するための推奨される方法は何ですか?

ActiveRecord::Base のドキュメントでは、クラス固有の接続について説明しています:

クラス固有の接続を設定することもできます。たとえば、Course が ActiveRecord::Base であるが、別のデータベースにある場合、Course.establish_connection と Course を指定するだけで、Course とそのすべてのサブクラスが代わりにこの接続を使用します。

セカンダリ データベースへの接続を指定するには、すべてのモデル クラスをサブクラス化する必要がありますか? (それも機能しますか?)

この宝石も見つけましたが、もうメンテナンスされていないようです.... magic_multi_connections gem ?

4

2 に答える 2

11

だから...私はこの解決策が好きです:

module Analytics

  class Base < ActiveRecord::Base
    self.abstract_class = true
    establish_connection ENV['ANALYTICS_DATABASE_URL']
  end

  class User < Base; end

  class Product < Base; end

end

これで、すべてが分析データベース (フォロワー) に接続するモデルができました。

分析アプリと通常のアプリの間でスコープまたはメソッドを共有する必要がある場合は、共有コードを mixin に配置し、それを Analytics または通常のモデルのいずれかに含めることができます。

または、分析に使用する前にコントローラーで分析に使用する必要があるモデルを呼び出すこともできますが.establish_connection、それによって他の通常の Web 要求に対する接続が混乱するかどうかはわかりません。次のリクエストでの通常のデータベース接続...

更新:別のアイデアが私を襲った:

class UserBase < ActiveRecord::Base
  self.abstract_class = true
  # all your user model code goes here
end

class User < UserBase
  establish_connection(Rails.env) # connect to your normal database
end

class AnalyticsUser < UserBase
  self.table_name = 'users'
  establish_connection(ENV['ANALYTICS_DATABASE_URL'])
end

これにより、モデルが分析用であろうと通常の Web 要求用であろうと、モデル間ですべてのコードを共有できますが、モデル名に応じて異なる接続を設​​定できます。

また、補足として、開発環境でフォロワーを設定したくない場合は、development.rb で ENV['ANALYTICS_DATABASE_URL'] を設定するだけです。

ENV['ANALYTICS_DATABASE_URL'] ||= 'postgres://localhost/myapp_development'

そして明らかに、Heroku では、ANALYTICS_DATABASE_URL の構成変数の名前を変更するか、フォロワーの DATABASE_URL が何であれ設定する必要があります。

于 2012-09-19T20:53:58.183 に答える
4

この質問によりよく答えるために: Heroku は、Octopus gem を使用してこの状況に対処する「公式の」方法を投稿しました

https://devcenter.heroku.com/articles/distributing-reads-to-followers-with-octopus

この gem を使用すると、完全に複製されたモデルを作成することも、 follower でブロックのみを実行することもできます。

Octopus.using(:slave_two) do
  User.create(:name => "Mike")
end
于 2014-05-04T17:53:12.727 に答える