【问题标题】:Rails :scope across databasesRails:跨数据库范围
【发布时间】:2012-11-07 14:39:38
【问题描述】:

我有三个模型,警报、站点、网络。它们通过belongs_to 关系连接,但它们存在于不同的数据库中

class Alarm < ActiveRecord::Base
   establish_connection :remote
   belongs_to :site, primary_key: :mac_address, foreign_key: :mac_address
end

class Site < ActiveRecord::Base
   establish_connection :remote
   belongs_to :network
end

class Network < ActiveRecord::Base
   establish_connection :local
end

我希望选择属于特定网络的所有警报。我可以在如下范围内使用原始 sql 执行此操作:

scope :network_alarms, lambda { |net|
    #need to ensure we are interrogating the right databases - network and site are local, alarm is remote
    remote=Alarm.connection.current_database
    local=Network.connection.current_database
    Alarm.find_by_sql("SELECT network.* FROM #{local}.network  INNER JOIN #{local}.site ON network.id = site.network_id  INNER JOIN #{remote}.alarm on #{remote}.alarm.mac_address = site.mac_address WHERE site.network_id=#{net.id}")
  }

这很好用。但是,这个范围返回一个数组,所以我不能链接它(例如,使用with_paginate's #page 方法)。所以

有没有更智能的方法来做这个加入。例如,我尝试过使用 joinwhere 语句(这是我尝试过的众多变体之一):

scope :network_alarms, lambda { |net| joins(:site).where("alarm.mac_address = site.mac_address").where('site.network_id=?', net) }

但问题似乎是 rails #join 假设两个表都在同一个数据库中,而没有检查每个表正在使用的连接。

【问题讨论】:

标签: ruby-on-rails scope named-scope


【解决方案1】:

所以当你知道怎么做时答案很简单......

ActiveRecord::Base 有一个table_name_prefix 方法,该方法将在查询中使用表名时添加特定前缀。如果重新定义这个方法,在表名前面加上数据库名,生成的SQL会被强制使用正确的数据库

所以,在我最初的问题中,我们将以下方法定义添加到表警报、站点和网络(以及其他任何需要的地方)中

def self.table_name_prefix
   self.connection.current_database+'.'
end

然后我们可以使用范围轻松构建连接

scope :network_alarms, lambda { |net| joins(:site => :network).where('site.network_id=?', net) }

感谢srosenhammer 的原始答案(这里:Rails 3 - Multiple database with joins condition

史蒂夫

【讨论】:

  • 如果它是您正在寻找的最佳答案,您应该接受您的答案。
猜你喜欢
  • 1970-01-01
  • 2021-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多