実行環境:
Rails 3.0.4
Rails 3.0.4
Railsでは基本的に1つのDBを使用するように設計されています。デフォルトで使用するDBは config/database.yml 内で、実行モード(Rails_Env:development/test/production)別にDBが指定されていますが、これらのデフォルトのDB以外のDBに接続するやり方です。
用途としては例えば、他のシステムで使用しているユーザテーブルを参照する(いわゆるレガシーDBというやつですね)、アクセスログデータを別のサーバ上に保管する、などといった場合があるでしょう。
ここで想定する外部DB/テーブルの条件
- 使用しているデータベースのアダプタがある
MySQL, PostgreSQL, SQLite3, Oracle, DB2, SQL Server, ...
- 使用するテーブルに、整数型の単独の主キーが存在する
- Railsアプリケーションのサーバからアクセスが可能
別サーバ上のSQLiteなどのSQLサーバになっていないDBは対象外
(そんな場合はこんな方法も ⇒ 新規RailsアプリからレガシーなDBを参照する方法 - 今日とは違う明日)
モデルを外部DBと結び付ける
1. モデル定義で外部DB接続を指定
普通のモデル定義の中でestablish_connectionというメソッドを呼び出します。connectionはシングルトンで動作するのでestablish_connectionが呼び出されると、デフォルトのDB接続の代わりに指定されたDB接続が使われます。# ... endclass User < ActiveRecord::Base establish_connection( :adapter => "mysql", :host => "dbserver", :database => "dbname", :username => "user", :password => "opensesame" )
テーブル名や主キー名を指定する
外部DBのテーブル名や主キー名がRailsの規約に沿っている場合は上記でOKですが、他システムのDBを参照する場合などテーブル名や主キー名が規約通りでない場合、使用するテーブル名や主キーのカラム名を指定してあげる必要があります# ... ) set_table_name "USER_TBL" set_primary_key "UID" # ... endこうするとデフォルトのDBのテーブルと同じように扱えます。 class User < ActiveRecord::Base establish_connection(
@user = User.find(1)
2. DB接続の設定をconfig/database.ymlに設定する
モデルの中にDB接続設定を直接記載するのではなくアプリケーションの設定として記載する方がスマートです。config/database.ymlの中にデフォルトのDB接続情報に加えて外部DBの接続情報を追加します。# ... test: # ... production: # ... legacy_db: adapter: mysql encoding: utf8 database: dbname username: user password: opensesame host: hostnamedevelopment:
# ... endclass User < ActiveRecord::Base establish_connection(:legacy_db)
3. 外部DB接続の定義ファイルを独立させる
例えばconfig/legacy_database.ymlという別ファイルにDB接続の設定を保存するとする。adapter: mysql encoding: utf8 database: dbname username: user password: opensesame host: hostname
# ... endclass User < ActiveRecord::Base config_legacy = YAML.load_file(Rails.root.join('config/legacy_database.yml')).symbolize_keys establish_connection(config_legacy)
同じ外部DBに接続するモデルが複数ある場合
各モデルに上記の方法(1, 2, 3のいずれか)の通りに書けばアクセスはできるようになります。が、コネクションプーリングを有効に活用するという観点からは、外部DB接続する親となるモデルを作り、親モデルを継承させて各モデルを作る方がよいようです。以下のようにすると、User1とUser2は接続先のDBは同じでも別々の接続を使います。(コネクションプールが2つ使われてしまいます。)
class User1 < ActiveRecord::Base establish_connection(:legacy_db) end
以下のように継承を使うとUser1とUser2は同じコネクションを使ってくれます。 class User2 < ActiveRecord::Base establish_connection(:legacy_db) end
class LegacyBase < ActiveRecord::Base establish_connection(:legacy_db) end
class User1 < LegacyBase end
class User2 < LegacyBase end
0 件のコメント:
コメントを投稿