やりたかったこと
- Rails で複数 DB につなぐ
- モデル内の
establish_connection
をするときに共通化
環境
- OSX(Yosemite 10.10.5)
- ruby 2.3.0
- Rails 4.2.5
DBの設定
config/database.yml
app/config/database.yml
default: &default
adapter: postgresql
pool: 5
database: <%= ENV['RAILS_DATABASE_DATABASE'] %>
username: <%= ENV['RAILS_DATABASE_USER'] %>
password: <%= ENV['RAILS_DATABASE_PASSWORD'] %>
development:
<<: *default
test:
<<: *default
production:
<<: *default
anotherdb:
<<: *default
database: <%= ENV['RAILS_ANOTHER_DATABASE_DATABASE'] %>
username: <%= ENV['RAILS_ANOTHER_DATABASE_USER'] %>
password: <%= ENV['RAILS_ANOTHER_DATABASE_PASSWORD'] %>
初期状態
最初はここのモデルについて、establish_connection
をしていたが、
app/models/hoge/user1.rb
class Hoge::User1 < ActiveRecorde::Base
establish_connection(:anotherdb)
end
app/models/hoge/user2.rb
class Hoge::User2 < ActiveRecorde::Base
establish_connection(:anotherdb)
end
共通化後(失敗)
残念なかんじなので、共通化したモデルをつくり、継承することに
app/models/hoge/base.rb
# 共通化したモデル
class Hoge::Base< ActiveRecorde::Base
establish_connection(:anotherdb)
end
app/models/hoge/user1.rb
class Hoge::User1 < Hoge::Base
end
app/models/hoge/user2.rb
class Hoge::User2 < Hoge::Base
end
これでいけるかと思いきや、
ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column user1.id does not exist
というエラーが出てしまった。
各モデルで別々にestablish_connection
をしたときはできたので、今回establish_connection
をした先の DB に id カラムがなかったのは直接の原因じゃなさそう。
どうやらSTI(単一継承テーブル)をActiveRecordがやろうとしているが、今回は親クラスと子クラスでテーブルが違うので、変なことになってそうな感じが
ググってたらRails でモデルを継承しているスライドが
参考
複数DBとRails
共通化後(成功)
親子のテーブルが違う場合は抽象クラスを定義しなければならないらしい。
そのため、self.abstract_class = true
を入れれば良さそう
app/models/hoge/base.rb
class Hoge::Base < ActiveRecorde::Base
self.abstract_class = true
establish_connection(:anotherdb)
end
これでモデルの共通化ができた