web-dev-qa-db-ja.com

Railsの複数のデータベース

これはできますか?単一のアプリケーションで、SQLiteを使用して多くのプロジェクトを管理します。私が欲しいのは、アプリが管理しているプロジェクトごとに異なるデータベースを持つことです。 URIのパラメーターに基づいて、使用するコピーを選択します。

これは、1。セキュリティのために行われます。私はこの種のプログラミングの初心者です。何らかの理由で、プロジェクトで作業中に別のプロジェクトが破損するのは望ましくありません。古いプロジェクト

51
luca

デフォルトでは、Railsはマルチデータベースアーキテクチャ向けに設計されておらず、ほとんどの場合、まったく意味がありません。しかし、はい、異なるデータベースと接続を使用できます。

ここにいくつかの参照があります:

39
Simone Carletti

各Railsインスタンスを制御および設定でき、それらがスタンバイ状態であるためリソースを浪費する余裕がある場合は、いくつかのトラブルを回避し、database.ymlを変更してデータベース接続を変更しますすべてのインスタンスで使用されます。パフォーマンスが心配な場合は、このアプローチでは効果がありません。

1つのデータベース上の単一の一意のテーブルにバインドされたモデルの場合、モデル内でestablished_connectionを呼び出すことができます。

establish_connection "database_name_#{Rails_ENV}"

ここで説明されているとおり: http://apidock.com/Rails/ActiveRecord/Base/establish_connection/class

1つのデータベースのテーブルを使用するモデルと、他のデータベースのテーブルを使用する他の異なるモデルがあります。

同一のテーブルがあり、異なるデータベースで共通であり、単一のモデルで共有されている場合、ActiveRecordは役に立ちません。 2009年に、Rails 2.3.8を使用して作業中のプロジェクトでこれを要求しました。各顧客用のデータベースがあり、データベースにIDの名前を付けました。 ApplicationController内の接続を変更するメソッド:

def change_database database_id = params[:company_id]
    return if database_id.blank?

    configuration = ActiveRecord::Base.connection.instance_eval { @config }.clone
    configuration[:database] = "database_name_#{database_id}_#{Rails_ENV}"

    MultipleDatabaseModel.establish_connection configuration
end

そして、そのメソッドをすべてのコントローラーにbefore_filterとして追加しました:

before_filter :change_database

したがって、各コントローラーのアクションごとに、params [:company_id]が定義および設定されると、データベースが正しいものに変更されます。

移行を処理するために、ActiveRecord :: Migrationを拡張し、すべての顧客を検索し、各IDでブロックを反復するメソッドを使用しました。

class ActiveRecord::Migration
    def self.using_databases *args
        configuration = ActiveRecord::Base.connection.instance_eval { @config }
        former_database = configuration[:database]

        companies = args.blank? ? Company.all : Company.find(args)

        companies.each do |company|
            configuration[:database] = "database_name_#{company[:id]}_#{Rails_ENV}"
            ActiveRecord::Base.establish_connection configuration

            yield self
        end

        configuration[:database] = former_database
        ActiveRecord::Base.establish_connection configuration
    end
end

これを行うと、2つの異なるデータベースから同じアクション内でクエリを作成することができなくなることに注意してください。 change_databaseを再度呼び出すことができますが、正しいデータベースにリンクされなくなったオブジェクトからクエリを実行するメソッドを使用しようとすると厄介になります。また、異なるデータベースに属するテーブルを結合できないことは明らかです。

これを適切に処理するには、ActiveRecordを大幅に拡張する必要があります。この問題を解決するためのプラグインが今までにあります。簡単な調査でこれがわかりました。

DB-Charmer: http://kovyrin.github.com/db-charmer/

やってみたい。あなたに合ったものを教えてください。

27
adeandrade

私はこれを他のデータベースを使用して私のモデルのトップに追加することでこれを乗り越えました

class Customer < ActiveRecord::Base
  ENV["Rails_ENV"] == "development" ? Host = 'devhost' : Host = 'prodhost'

  self.establish_connection(
      :adapter  => "mysql",
      :Host     => "localhost",
      :username => "myuser",
      :password => "mypass",
      :database => "somedatabase"
    )
12
rdaniels

これらすべてのソリューションでは、カスタムデータベース接続を閉じることを忘れないでください。 will接続が不足すると、奇妙なリクエストタイムアウトの問題が発生します。

簡単な解決策はclear_active_connectionsです!コントローラーのafter_filterで。

after_filter :close_custom_db_connection

def close_custom_db_connection
  MyModelWithACustomDBConnection.clear_active_connections!
end
2
Steven Soroka

これまでのところ私が見つけた最良の解決策はこれです:

アプローチできるデータベースアーキテクチャは3つあります。

  • 単一テナント用の単一データベース
  • テナントごとに個別のスキーマ
  • テナントの共有スキーマ

注:彼らには特定の長所と短所があり、ユースケースによって異なります。

私はこれからこれを得ました ブログ !私にとって非常に役立ちます。

Gem Apartment をRailsに使用できます

Gorails for apartment でフォローできるビデオリファレンス

0

この質問で説明したのは、マルチテナンシー(それぞれに異なるデータを持つ同一構造のデータベース)です。 Apartment gem はこれに最適です。

Railsの複数のデータベースに関する一般的な質問:ActiveRecordは複数のデータベースをサポートしていますが、Railsはそれらを管理する方法を提供していません。最近、 Multiverse gemを作成しましたこれに対処します。

0
Andrew Kane

あなたのconfig/database.ymlでこのようなことをしてください

default: &default
  adapter: postgresql
  encoding: unicode
  pool: 5

development:
  <<: *default
  database: mysite_development

test:
  <<: *default
  database: mysite_test

production:
  <<: *default
  Host: 10.0.1.55
  database: mysite_production
  username: postgres_user
  password: <%= ENV['DATABASE_PASSWORD'] %>

db2_development:
  <<: *default
  database: db2_development

db2_test:
  <<: *default
  database: db2_test

db2_production:
  <<: *default
  Host: 10.0.1.55
  database: db2_production
  username: postgres_user
  password: <%= ENV['DATABASE_PASSWORD'] %>

次に、モデルでdb2を参照できます

class Customers < ActiveRecord::Base
  establish_connection "db2_#{Rails.env}".to_sym
end
0
rdaniels