문제

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.

도움이 되었습니까?

해결책

Try to establish_connection in ContentItem too.

다른 팁

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top