我正在尝试设置一个has_many:通过两个模型之间的关系 User和CustomerAccount通过另一个加入模型AccountOwnership (users和account_ownerships表位于一个db中,比如说db1,而customer_accounts表位于远程db中,比如说db2)。
以下是设置关联的相关代码
class User < ActiveRecord::Base
has_many :account_ownerships, :dependent => :destroy
has_many :companies, :through => :account_ownerships
end
class AccountOwnership < ActiveRecord::Base
belongs_to :user
belongs_to :company, :class_name => "Reporting::CustomerAccount"
end
class CustomerAccount < Reporting::Base
set_table_name 'customers'
establish_connection("db2_#{RAILS_ENV}")
end
config / database.yml(配置正确,虽然此处未显示)
development:
reconnect: false
database: db1
pool: 5
db2_development:
reconnect: false
database: db2
host: different.host
pool: 5
在脚本/控制台中
a = AccountOwnership.new(:user_id => 2, :company_id => 10)
a.user ## Returns the correct user
a.company ## returns the correct CustomerAccount instance
也
a.user.account_ownership ## returns a as anticipated
但
a.user.companies ## produces the following error:
#ActiveRecord::StatementInvalid: Mysql::Error: Table #'db2.account_ownerships' doesn't exist: SELECT `customers`.* FROM #`customers` INNER JOIN `account_ownerships` ON `customers`.id = #`account_ownerships`.company_id WHERE ((`account_ownerships`.user_id = 4))
这里的问题是“account_ownerships”和“users”表包含在中 一个默认数据库(比如db1),其中包含“customers”表 一个不同的数据库(比如db2)。与数据库的连接是 配置正确,但在查找期间,因为只有一个数据库 连接对象可用,Rails尝试查找account_ownerships db2中的数据库因此失败。
看起来我的设计/逻辑可能存在缺陷,因为我看不到任何方法 使用相同的数据库连接连接到两个不同的数据库,但我 会很高兴看到是否有一个解决方法,而不改变 设计。 (我不愿意改变设计,因为db2不在我的下面 控制)
看起来我可以通过将我的account_ownerships表移动到db2来解决此问题,但这对我来说不太理想。
是否有任何备用机制/架构来设置此关联 轨。
提前致谢。 中号
答案 0 :(得分:1)
解决方案:
似乎无法通过任何Rails关联魔法实现这一点,因为这是包括原始SQL在内的任何数据库访问机制的核心限制。
以下是我解决此问题的方法:
class User < ActiveRecord::Base
has_many :account_ownerships, :dependent => :destroy
def companies
(account_ownerships.collect { |r| Reporting::CustomerAccount.find(r.company_id) }).flatten
end
end
这提供了正确的近似值,如下所示:
a = AcccountOwnership.create!(:user_id => 10, :company_id => 10)
u = User.find(10)
u.account_ownerships ### will return the correct account_ownership instance
ALSO
u.companies ### will return a list of all companies enlisted for each account
我们需要在account_ownership模型中添加两个实例方法来进行近似 关联行为
class CustomerAccount < ActiveRecord::Base
set_table_name "customers"
########################################################
## This cannot be used because, customers and
## account_ownerships tables are contained in
## different databases, because of this it is
## impossible to query these two tables from a
## single db connection, which is what we are
## attempting to achieve here.
## has_many :account_ownerships, :dependent => :destroy
########################################################
def account_ownerships
AccountOwnership.find(:all, :conditions => ["company_id = ?", self.id])
end
def users
(account_ownerships.collect { |r| User.find(r.user_id) }).flatten
end
end
现在我们可以做到
c = CustomerAccount.find(10)
c.account_ownerships ## will return the right ownership accounts
和
c.users ## will iterate over all the accounts accumulating any users
注意: 1.由于CustomerAccount模型上没有删除级联,如果删除了任何帐户,这将不会反映在account_ownership表中,因此这会在users方法中引起丑陋的ActiveRecord :: RecordNotFound错误。