【问题标题】:Rails: setting up has_many_through association between tables from different databasesRails:在来自不同数据库的表之间设置 has_many_through 关联
【发布时间】:2010-09-29 21:18:18
【问题描述】:

我正在尝试设置一个 has_many :through 两个模型之间的关系 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: 表 #'db2.account_ownerships' 不存在: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),“客户”表包含在 一个不同的数据库(比如 db2)。与数据库的连接是 配置正确,但在查找过程中,因为只有一个数据库 连接对象可用,Rails 尝试查找 account_ownerships db2 中的数据库,因此失败。

看起来我的设计/逻辑可能有缺陷,因为我看不到方法 使用相同的数据库连接连接到两个不同的数据库,但我 很高兴看到是否有解决方法,而无需更改 设计。 (我不愿意更改设计,因为 db2 不在我的 控制)

看起来我可以通过将 account_ownerships 表移动到 db2 来解决这个问题,但这至少对我来说不太理想。

是否有任何替代机制/模式来设置此关联 导轨。

提前致谢。 M

【问题讨论】:

    标签: ruby-on-rails activerecord has-many-through model-associations


    【解决方案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
    

    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 错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多