Rails7:切换到不同的数据库
Rails 7: switch to different databases
我试图在我的脚本中连接到不同的数据库,但我得到 ActiveRecord::ConnectionNotEstablished: No connection pool for 'ActiveRecord::Base' found for the 'main' shard.
来自database.yml
的相关代码如下
test:
primary:
adapter: postgresql
database: test
database: "<%= ENV['DATABASE_NAME'] %>"
username: "<%= ENV['DATABASE_USERNAME'] %>"
password: "<%= ENV['DATABASE_PASSWORD'] %>"
host: "<%= ENV['DATABASE_HOST'] %>"
main:
adapter: postgresql
username: postgres
database: "<%= ENV['API_MAIN_DATABASE_NAME'] %>"
password: "<%= ENV['API_DATABASE_PASSWORD'] %>"
host: "<%= ENV['API_DATABASE_HOST'] %>"
database_tasks: false
prediction:
adapter: postgresql
username: postgres
database: "<%= ENV['API_PREDICTION_DATABASE_NAME'] %>"
password: "<%= ENV['API_DATABASE_PASSWORD'] %>"
host: "<%= ENV['API_DATABASE_HOST'] %>"
database_tasks: false
onshore:
adapter: postgresql
username: postgres
database: "<%= ENV['API_US_ONSHORE_DATABASE_NAME'] %>"
password: "<%= ENV['API_DATABASE_PASSWORD'] %>"
host: "<%= ENV['API_DATABASE_HOST'] %>"
database_tasks: false
我有 3 个模型连接到 main
、prediction
和 onshore
数据库,如下所示
class ExternalRecord < ApplicationRecord
self.abstract_class = true
connects_to shards: { writing: :primary, reading: :main }
end
class ExternalRecordPrediction < ApplicationRecord
self.abstract_class = true
connects_to shards: { writing: :primary, reading: :prediction }
end
class ExternalRecordOnshore < ApplicationRecord
self.abstract_class = true
connects_to shards: { writing: :primary, reading: :onshore }
end
我正在尝试通过在循环中连接到这三个不同的数据库来进行一些处理,如下所示
ActiveRecord::Base.connected_to(role: :reading, shard: :main) do
results = ActiveRecord::Base.connection.execute(query_here)
#process results
但是我得到一个错误ActiveRecord::ConnectionNotEstablished: No connection pool for 'ActiveRecord::Base' found for the 'main' shard.
如何在脚本中切换到不同的数据库。
我正在使用 Rails 7
我之前使用 Rails 5
并使用 ar-octopus
来实现这一点。
ActiveRecord::Base
与您的 ApplicationRecord
class 或设置了 primary_abstract_class
的其他 class 共享连接。你必须在那里设置connects_to
。
class ApplicationRecord < ActiveRecord::Base
primary_abstract_class # <= there can only be one in your app
connects_to database: { writing: :primary, reading: :main }
end
# if you are in a console make sure ApplicationRecord class is loaded
ApplicationRecord
ActiveRecord::Base.connected_to(role: :reading) do
# ActiveRecord::Base.current_role # => :reading
# ActiveRecord::Base.current_shard # => :default
# :default is configuration named 'primary' or the first entry if 'primary' is not found
# ActiveRecord::Base.connection.execute("INSERT ...") # => ActiveRecord::ReadOnlyError
ActiveRecord::Base.connection.execute("SELECT ...") # ok
end
有碎片
class ApplicationRecord < ActiveRecord::Base
primary_abstract_class
connects_to shards: {
one: { writing: :primary, reading: :main },
# two: ...
}
end
# if you are in a console make sure ApplicationRecord class is loaded
ApplicationRecord
ActiveRecord::Base.connected_to(role: :reading, shard: :one) do
# ActiveRecord::Base.current_role # => :reading
# ActiveRecord::Base.current_shard # => :one
# ActiveRecord::Base.connection.execute("INSERT ...") # => ActiveRecord::ReadOnlyError
ActiveRecord::Base.connection.execute("SELECT ...") # ok
end
参考:
rails v7.0.2.3
ruby v3.1.1
- https://guides.rubyonrails.org/active_record_multiple_databases.html#setting-up-your-application
- https://api.rubyonrails.org/classes/ActiveRecord/Inheritance/ClassMethods.html#method-i-primary_abstract_class
- https://api.rubyonrails.org/classes/ActiveRecord/ConnectionHandling.html#method-i-connects_to
您也可以只强制连接。但我不知道这有多安全,我不会在主应用程序中使用它。
ActiveRecord::Base.establish_connection(:prediction)
# do it here
ActiveRecord::Base.establish_connection # back to default just in case
我试图在我的脚本中连接到不同的数据库,但我得到 ActiveRecord::ConnectionNotEstablished: No connection pool for 'ActiveRecord::Base' found for the 'main' shard.
来自database.yml
的相关代码如下
test:
primary:
adapter: postgresql
database: test
database: "<%= ENV['DATABASE_NAME'] %>"
username: "<%= ENV['DATABASE_USERNAME'] %>"
password: "<%= ENV['DATABASE_PASSWORD'] %>"
host: "<%= ENV['DATABASE_HOST'] %>"
main:
adapter: postgresql
username: postgres
database: "<%= ENV['API_MAIN_DATABASE_NAME'] %>"
password: "<%= ENV['API_DATABASE_PASSWORD'] %>"
host: "<%= ENV['API_DATABASE_HOST'] %>"
database_tasks: false
prediction:
adapter: postgresql
username: postgres
database: "<%= ENV['API_PREDICTION_DATABASE_NAME'] %>"
password: "<%= ENV['API_DATABASE_PASSWORD'] %>"
host: "<%= ENV['API_DATABASE_HOST'] %>"
database_tasks: false
onshore:
adapter: postgresql
username: postgres
database: "<%= ENV['API_US_ONSHORE_DATABASE_NAME'] %>"
password: "<%= ENV['API_DATABASE_PASSWORD'] %>"
host: "<%= ENV['API_DATABASE_HOST'] %>"
database_tasks: false
我有 3 个模型连接到 main
、prediction
和 onshore
数据库,如下所示
class ExternalRecord < ApplicationRecord
self.abstract_class = true
connects_to shards: { writing: :primary, reading: :main }
end
class ExternalRecordPrediction < ApplicationRecord
self.abstract_class = true
connects_to shards: { writing: :primary, reading: :prediction }
end
class ExternalRecordOnshore < ApplicationRecord
self.abstract_class = true
connects_to shards: { writing: :primary, reading: :onshore }
end
我正在尝试通过在循环中连接到这三个不同的数据库来进行一些处理,如下所示
ActiveRecord::Base.connected_to(role: :reading, shard: :main) do
results = ActiveRecord::Base.connection.execute(query_here)
#process results
但是我得到一个错误ActiveRecord::ConnectionNotEstablished: No connection pool for 'ActiveRecord::Base' found for the 'main' shard.
如何在脚本中切换到不同的数据库。
我正在使用 Rails 7
我之前使用 Rails 5
并使用 ar-octopus
来实现这一点。
ActiveRecord::Base
与您的 ApplicationRecord
class 或设置了 primary_abstract_class
的其他 class 共享连接。你必须在那里设置connects_to
。
class ApplicationRecord < ActiveRecord::Base
primary_abstract_class # <= there can only be one in your app
connects_to database: { writing: :primary, reading: :main }
end
# if you are in a console make sure ApplicationRecord class is loaded
ApplicationRecord
ActiveRecord::Base.connected_to(role: :reading) do
# ActiveRecord::Base.current_role # => :reading
# ActiveRecord::Base.current_shard # => :default
# :default is configuration named 'primary' or the first entry if 'primary' is not found
# ActiveRecord::Base.connection.execute("INSERT ...") # => ActiveRecord::ReadOnlyError
ActiveRecord::Base.connection.execute("SELECT ...") # ok
end
有碎片
class ApplicationRecord < ActiveRecord::Base
primary_abstract_class
connects_to shards: {
one: { writing: :primary, reading: :main },
# two: ...
}
end
# if you are in a console make sure ApplicationRecord class is loaded
ApplicationRecord
ActiveRecord::Base.connected_to(role: :reading, shard: :one) do
# ActiveRecord::Base.current_role # => :reading
# ActiveRecord::Base.current_shard # => :one
# ActiveRecord::Base.connection.execute("INSERT ...") # => ActiveRecord::ReadOnlyError
ActiveRecord::Base.connection.execute("SELECT ...") # ok
end
参考:
rails v7.0.2.3
ruby v3.1.1
- https://guides.rubyonrails.org/active_record_multiple_databases.html#setting-up-your-application
- https://api.rubyonrails.org/classes/ActiveRecord/Inheritance/ClassMethods.html#method-i-primary_abstract_class
- https://api.rubyonrails.org/classes/ActiveRecord/ConnectionHandling.html#method-i-connects_to
您也可以只强制连接。但我不知道这有多安全,我不会在主应用程序中使用它。
ActiveRecord::Base.establish_connection(:prediction)
# do it here
ActiveRecord::Base.establish_connection # back to default just in case