Try to establish_connection
in ContentItem
too.
Cannot connect to two postgres databases in rails 3.2.
-
03-06-2022 - |
문제
I've tried a few methods found on stack overflow for connecting to two database in rails two however non of them are working. Here's what I've got at the moment:
In the database.yml there's two connection settings:
development:
adapter: postgresql
host: localhost
database: blerg
username: postgres
encoding: utf8
production:
blah...
test: &test
blah...
cucumber:
<<: *test
static_api_development:
adapter: postgresql
host: localhost
database: blerg-static-api
username: postgres
encoding: utf8
static_api_production:
blah...
static_api_test:
blah...
And then I have lots of normal models in the rails app, but also the odd special model that need to connect to the other database, here's how I've set it up...
There is a module in the models folder called static_table.rb which has this content:
class StaticTable < ActiveRecord::Base
self.abstract_class = true
establish_connection "static_api_#{Rails.env}"
end
Then the special models that need the other tables have this:
class ContentItem < StaticTable
self.table_name = 'content_items'
end
However if you call ContentItem.all in a controller it says the 'content_items' table does not exist and the database connection is showing as 'blerg' not the 'blerg-static-api' which it should be.
Any help would be much appreciated thanks.
해결책
다른 팁
The issue is that inheritance doesn't work that way.
Consider the source of #establish_connection
:
def establish_connection(owner, spec)
@class_to_pool.clear
raise RuntimeError, "Anonymous class is not allowed." unless owner.name
owner_to_pool[owner.name] = ConnectionAdapters::ConnectionPool.new(spec)
end
(Let's suppose owner_to_pool
is actually @owner_to_pool
for simplicity.)
Inside the StaticTable class, you invoked establish_connection
within the class context. This updates @class_to_pool
and @owner_to_pool
, which are instance variables of StaticTable. (Some refer to these as class instance variables.) The accepted answer in this question goes into a detailed explanation.
The main problem is that even though ContentItem extends StaticTable, it does not inherit @class_to_pool
and @owner_to_pool
, and thus does not know that it should be establishing a connection to static_api_*
.
There are two ways to fix this. First, you can use establish_connection
in every model that should be using a static_api_*
connection. This is simple, but not DRY. A better way is to create a Rails concern and include it in the necessary models.
module StaticConnectionConcern
extend ActiveSupport::Concern
included do
establish_connection "static_api_#{Rails.env}"
end
end
Then in your models,
class ContentItem < ActiveRecord::Base
include StaticConnectionConcern
end
Using Rails concerns, when StaticConnectionConcern
is included in ContentItem
, whatever is inside the included
block is invoked in ContentItem
's class context. You can create a app/concerns
directory for concerns, and then tell Rails to autoload them by editing config/application.rb
:
config.autoload_paths += %W(#{Rails.root}/app/concerns)
I strongly recommend the second way. As your application grows and becomes more complex, the StaticConnectionConcern might grow to include other methods as well.