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”不存在
它将不支持联接,您必须创建一个角色和