我已经尝试了一些在堆栈溢出上找到的方法来连接到rails 2中的两个数据库,但是没有它们正在工作。这就是我现在所拥有的:
在database.yml中有两个连接设置:
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...
然后我在rails应用程序中有很多普通模型,还有需要连接到其他数据库的奇怪特殊模型,这就是我如何设置它...
models文件夹中有一个名为static_table.rb的模块,其中包含以下内容:
class StaticTable < ActiveRecord::Base
self.abstract_class = true
establish_connection "static_api_#{Rails.env}"
end
然后需要其他表的特殊模型具有:
class ContentItem < StaticTable
self.table_name = 'content_items'
end
但是,如果在控制器中调用ContentItem.all,则表示'content_items'表不存在,并且数据库连接显示为'blerg'而不是'blerg-static-api'应该是。
非常感谢任何帮助。
答案 0 :(得分:1)
尝试establish_connection
中的ContentItem
。
答案 1 :(得分:1)
我的多个数据库连接的例子,可能会对你有帮助。在我的例子中,我使用crm_admin从我们的子域中获取公司信息。子域是使用自己的数据库运行的各个应用程序。 注意! database.yml可能看起来很奇怪,但是当添加或删除子域时,它会自动使用YML生成。
production:
adapter: postgresql
encoding: utf8
reconnect: false
database: crm_admin
username: username
password: passwrod
pool: 5
simtravel_crm:
adapter: postgresql
database: simtravel_crm_production
username: simtravel_username
password: simtravel_password
encoding: utf8
pool: 5
reconnect: 'false'
oktell_crm:
adapter: postgresql
database: oktell_crm_production
username: oktell_username
password: oktell_password
encoding: utf8
pool: 5
reconnect: 'false'
design_crm:
adapter: postgresql
database: design_crm_production
username: design_username
password: design_password
encoding: utf8
pool: 5
reconnect: 'false'
从oktell_crm_production数据库获取公司:
应用/模型/ oktell_crm.rb 强>
class OktellCrm < ActiveRecord::Base
end
class OktellCompany < ActiveRecord::Base
establish_connection "oktell_crm"
set_table_name 'companies'
end
应用/视图/子域/ _companies.html.erb 强>
首先我要加载正确的模型,在oktell的情况下我会companies = OktellCompany.all
:
<%
model_name = ("#{@subdomain.name.downcase.capitalize}Company").singularize.classify.constantize
companies = model_name.all
%>
<div class="model">
<b>Companies in <%= @subdomain.name %> subdomain: <%= companies.count %></b>
<table>
<thead>
<tr>
<th>Name</th>
<th>Created at</th>
</tr>
</thead>
<tbody>
<% companies.each do |company| %>
<tr>
<td><%= company.name %></td>
<td><%= l company.created_at, format: :long %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
P.S。对于视图部分,必须有一个更好的解决方案,但这足以满足我的需求。
答案 2 :(得分:0)
考虑#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
(为简单起见,我们假设owner_to_pool
实际上是@owner_to_pool
。)
在StaticTable类中,您在类上下文中调用了establish_connection
。这会更新@class_to_pool
和@owner_to_pool
,它们是 StaticTable 的实例变量。 (有些人将这些称为类实例变量。)this question中接受的答案进入详细解释。
主要问题是即使ContentItem扩展了StaticTable,它也不会继承@class_to_pool
和@owner_to_pool
,因此不知道它应该与static_api_*
建立连接。 / p>
有两种方法可以解决这个问题。首先,您可以在应使用establish_connection
连接的每个模型中使用static_api_*
。这很简单,但不是DRY。更好的方法是创建Rails concern并将其包含在必要的模型中。
module StaticConnectionConcern
extend ActiveSupport::Concern
included do
establish_connection "static_api_#{Rails.env}"
end
end
然后在你的模特中,
class ContentItem < ActiveRecord::Base
include StaticConnectionConcern
end
使用Rails问题,当StaticConnectionConcern
中包含ContentItem
时,included
块中的任何内容都会在ContentItem
的类上下文中调用。您可以为关注点创建一个app/concerns
目录,然后通过编辑config/application.rb
告诉Rails自动加载它们:
config.autoload_paths += %W(#{Rails.root}/app/concerns)
我强烈推荐第二种方式。随着应用程序的增长和变得越来越复杂,StaticConnectionConcern也可能会增长到包含其他方法。