Ruby on rails 可以在Rails中跨多个数据库进行内部连接吗?

Ruby on rails 可以在Rails中跨多个数据库进行内部连接吗?,ruby-on-rails,postgresql,join,activerecord,Ruby On Rails,Postgresql,Join,Activerecord,我很难使用有很多:通过关联访问数据,其中一些表位于单独的数据库中 # database_one class Input < ApplicationRecord belongs_to :user # Works great end # database_two class User < AbstractClass belongs_to :group # Works great has_many :inputs # Works great end

我很难使用
有很多:通过
关联访问数据,其中一些表位于单独的数据库中

# database_one
class Input < ApplicationRecord
  belongs_to :user      # Works great
end

# database_two
class User < AbstractClass
  belongs_to :group     # Works great
  has_many :inputs      # Works great
end

# database_two
class Group < AbstractClass
  has_many :users                     # Works great
  has_many :inputs, through: :users   # Does not work at all
end

class AbstractClass < ApplicationRecord
  self.abstract_class = true
  establish_connection "database_two_#{Rails.env}".to_sym
end
看起来不可能跨两个数据库进行
内部联接
?我能做些什么来缓解这种情况吗?
我曾尝试将此方法添加到
抽象类
中,但不幸的是,它没有解决任何问题:

def self.table_name_prefix
  "database_two_#{Rails.env}."
end
作为一种解决方法,我在组模型中添加了以下内容,但这不是我正在寻找的解决方案

def inputs
  Input.where(id: users.ids)
end

我认为不可能在一个查询中连接两个不同的表。您可以使用Ruby来获得最终的收藏。 使用一个查询从一个数据库获取集合,然后从另一个查询获取另一个集合。
然后使用Ruby从这两个集合中选择/筛选。我希望这对您有所帮助。

我认为不可能在一个查询中连接两个不同的表。您可以使用Ruby来获得最终的收藏。 使用一个查询从一个数据库获取集合,然后从另一个查询获取另一个集合。 然后使用Ruby从这两个集合中选择/筛选。我希望这对您有所帮助。

我就是这样做的(假设两个数据库运行在同一台主机上):

1/为第二个数据库创建一个database.yml文件 这很重要,因为它将允许您通过Rails方式连接到第二个数据库。我相信您已经进行了设置,但对于遇到此问题的未来开发人员,可以按如下方式进行:

class DatabaseTwoModel < ApplicationRecord
  self.abstract_class = true
  establish_connection DATABASE_TWO

  def self.table_name_prefix
    "database_two_#{Rails.env}."
  end
end
class User < DatabaseTwoModel
  belongs_to :group
  has_many :inputs
end

class Group < DatabaseTwoModel
  has_many :users
  has_many :inputs, through: :users
end
config/database.yml

development:
  adapter: postgresql
  encoding: unicode
  database: database_one_development
  pool: 5
  username: USERNAME
  password: PASSWORD

test:
  adapter: postgresql
  encoding: unicode
  database: database_one_test
  pool: 5
  username: USERNAME
  password: PASSWORD

production:
  adapter: postgresql
  encoding: unicode
  database: database_one_production
  pool: 5
  username: USERNAME
  password: PASSWORD
development:
  adapter: postgresql
  encoding: unicode
  database: database_two_development
  pool: 5
  username: USERNAME
  password: PASSWORD

test:
  adapter: postgresql
  encoding: unicode
  database: database_two_test
  pool: 5
  username: USERNAME
  password: PASSWORD

production:
  adapter: postgresql
  encoding: unicode
  database: database_two_production
  pool: 5
  username: USERNAME
  password: PASSWORD
config/database_two.yml

development:
  adapter: postgresql
  encoding: unicode
  database: database_one_development
  pool: 5
  username: USERNAME
  password: PASSWORD

test:
  adapter: postgresql
  encoding: unicode
  database: database_one_test
  pool: 5
  username: USERNAME
  password: PASSWORD

production:
  adapter: postgresql
  encoding: unicode
  database: database_one_production
  pool: 5
  username: USERNAME
  password: PASSWORD
development:
  adapter: postgresql
  encoding: unicode
  database: database_two_development
  pool: 5
  username: USERNAME
  password: PASSWORD

test:
  adapter: postgresql
  encoding: unicode
  database: database_two_test
  pool: 5
  username: USERNAME
  password: PASSWORD

production:
  adapter: postgresql
  encoding: unicode
  database: database_two_production
  pool: 5
  username: USERNAME
  password: PASSWORD
config/initializers/database_connector.rb

DATABASE_ONE_DB = YAML.load_file(File.join(Rails.root, "config", "database.yml"))[Rails.env.to_s]
DATABASE_TWO_DB = YAML.load_file(File.join(Rails.root, "config", "database_two.yml"))[Rails.env.to_s]
2/如下设置您的AbstractClass:

class DatabaseTwoModel < ApplicationRecord
  self.abstract_class = true
  establish_connection DATABASE_TWO

  def self.table_name_prefix
    "database_two_#{Rails.env}."
  end
end
class User < DatabaseTwoModel
  belongs_to :group
  has_many :inputs
end

class Group < DatabaseTwoModel
  has_many :users
  has_many :inputs, through: :users
end
它本身确实工作得很好,但在进行内部联接时,可能会弄乱SQL查询

4/Rspec

如果您使用的是Rspec,则需要将其添加到
rails\u helper.rb
文件中:

database_one = Rails.configuration.database_configuration[Rails.env]
database_two = YAML.load_file(File.join(Rails.root, "config", "database_two.yml"))[Rails.env]

# start by truncating all the tables but then use the faster
# transaction strategy the rest of the time.
config.before(:suite) do
  ActiveRecord::Base.establish_connection database_two
  DatabaseCleaner.clean_with(:truncation)
  DatabaseCleaner.strategy = :transaction
  ActiveRecord::Base.establish_connection database_one
  DatabaseCleaner.clean_with(:truncation)
  DatabaseCleaner.strategy = :transaction
end
这会清理数据库,测试将顺利运行

您应该能够运行您的查询以及您的多个查询

不同的主机

如果数据库位于不同的主机上,则可以查看gem。它很古老,但对如何处理这个问题有很好的理解

我希望这有帮助

我就是这样做的(假设两个数据库运行在同一台主机上):

1/为第二个数据库创建一个database.yml文件 这很重要,因为它将允许您通过Rails方式连接到第二个数据库。我相信您已经进行了设置,但对于遇到此问题的未来开发人员,可以按如下方式进行:

class DatabaseTwoModel < ApplicationRecord
  self.abstract_class = true
  establish_connection DATABASE_TWO

  def self.table_name_prefix
    "database_two_#{Rails.env}."
  end
end
class User < DatabaseTwoModel
  belongs_to :group
  has_many :inputs
end

class Group < DatabaseTwoModel
  has_many :users
  has_many :inputs, through: :users
end
config/database.yml

development:
  adapter: postgresql
  encoding: unicode
  database: database_one_development
  pool: 5
  username: USERNAME
  password: PASSWORD

test:
  adapter: postgresql
  encoding: unicode
  database: database_one_test
  pool: 5
  username: USERNAME
  password: PASSWORD

production:
  adapter: postgresql
  encoding: unicode
  database: database_one_production
  pool: 5
  username: USERNAME
  password: PASSWORD
development:
  adapter: postgresql
  encoding: unicode
  database: database_two_development
  pool: 5
  username: USERNAME
  password: PASSWORD

test:
  adapter: postgresql
  encoding: unicode
  database: database_two_test
  pool: 5
  username: USERNAME
  password: PASSWORD

production:
  adapter: postgresql
  encoding: unicode
  database: database_two_production
  pool: 5
  username: USERNAME
  password: PASSWORD
config/database_two.yml

development:
  adapter: postgresql
  encoding: unicode
  database: database_one_development
  pool: 5
  username: USERNAME
  password: PASSWORD

test:
  adapter: postgresql
  encoding: unicode
  database: database_one_test
  pool: 5
  username: USERNAME
  password: PASSWORD

production:
  adapter: postgresql
  encoding: unicode
  database: database_one_production
  pool: 5
  username: USERNAME
  password: PASSWORD
development:
  adapter: postgresql
  encoding: unicode
  database: database_two_development
  pool: 5
  username: USERNAME
  password: PASSWORD

test:
  adapter: postgresql
  encoding: unicode
  database: database_two_test
  pool: 5
  username: USERNAME
  password: PASSWORD

production:
  adapter: postgresql
  encoding: unicode
  database: database_two_production
  pool: 5
  username: USERNAME
  password: PASSWORD
config/initializers/database_connector.rb

DATABASE_ONE_DB = YAML.load_file(File.join(Rails.root, "config", "database.yml"))[Rails.env.to_s]
DATABASE_TWO_DB = YAML.load_file(File.join(Rails.root, "config", "database_two.yml"))[Rails.env.to_s]
2/如下设置您的AbstractClass:

class DatabaseTwoModel < ApplicationRecord
  self.abstract_class = true
  establish_connection DATABASE_TWO

  def self.table_name_prefix
    "database_two_#{Rails.env}."
  end
end
class User < DatabaseTwoModel
  belongs_to :group
  has_many :inputs
end

class Group < DatabaseTwoModel
  has_many :users
  has_many :inputs, through: :users
end
它本身确实工作得很好,但在进行内部联接时,可能会弄乱SQL查询

4/Rspec

如果您使用的是Rspec,则需要将其添加到
rails\u helper.rb
文件中:

database_one = Rails.configuration.database_configuration[Rails.env]
database_two = YAML.load_file(File.join(Rails.root, "config", "database_two.yml"))[Rails.env]

# start by truncating all the tables but then use the faster
# transaction strategy the rest of the time.
config.before(:suite) do
  ActiveRecord::Base.establish_connection database_two
  DatabaseCleaner.clean_with(:truncation)
  DatabaseCleaner.strategy = :transaction
  ActiveRecord::Base.establish_connection database_one
  DatabaseCleaner.clean_with(:truncation)
  DatabaseCleaner.strategy = :transaction
end
这会清理数据库,测试将顺利运行

您应该能够运行您的查询以及您的多个查询

不同的主机

如果数据库位于不同的主机上,则可以查看gem。它很古老,但对如何处理这个问题有很好的理解



我希望这有帮助

我很肯定这是对的。如果你对数据库有控制权,你也许可以用一些东西来绕过它,比如我很确定这是对的。如果你能控制数据库,你也许可以用一些我以前没有用过Rails的东西来绕过它,但这里有两点:1)我知道你不是在追求纯SQL解决方案,但我曾经使用过应用程序/ORM,在这些应用程序/ORM中,不可能对数据库进行复杂的查询,我使用的解决方法是编写视图或基于表的存储过程。2) PostgreSQL既有架构又有数据库:跨架构连接很好,不可能跨数据库连接您的数据库在同一台主机上吗?@Jeremie:是的。@ardavis很棒。我下面的答案应该有用。你试过了吗?抱歉耽搁了。我今天没能完成那个项目。不过,我明天要试一试!我以前没有使用过Rails,但这里有几点:1)我知道您不是在追求纯SQL解决方案,但我使用过应用程序/ORM,在这些应用程序/ORM中,无法对数据库进行复杂查询,我使用的解决方法是编写视图或基于表的存储过程。2) PostgreSQL既有架构又有数据库:跨架构连接很好,不可能跨数据库连接您的数据库在同一台主机上吗?@Jeremie:是的。@ardavis很棒。我下面的答案应该有用。你试过了吗?抱歉耽搁了。我今天没能完成那个项目。不过,我明天要试一试!对不起,这个解决方案对我不起作用
ActiveRecord::StatementInvalid:PG::UndefinedTable:ERROR:relation“database\u two\u name.groups”不存在
此外,如果我向database one models添加
self.table\u name\u前缀
,我会得到相同的错误,但是
ERROR:relation“database\u one\u name.groups”不存在
它将不支持联接,您必须创建一个角色,并与数据库的用户共享。很抱歉,此解决方案不适用于我
ActiveRecord::StatementInvalid:PG::UndefinedTable:ERROR:relation“database\u two\u name.groups”不存在
此外,如果我向database one models添加
self.table\u name\u前缀
,我会得到相同的错误,但是
ERROR:relation“database\u one\u name.groups”不存在
它将不支持联接,您必须创建一个角色和