модуль ActiveRecord::ConnectionHandling
Константы
- DEFAULT_ENV
- RAILS_ENV
Атрибуты
Открытые методы экземпляров
# File activerecord/lib/active_record/connection_handling.rb, line 261
def clear_query_caches_for_current_thread
if ActiveRecord::Base.legacy_connection_handling
ActiveRecord::Base.connection_handlers.each_value do |handler|
clear_on_handler(handler)
end
else
clear_on_handler(ActiveRecord::Base.connection_handler)
end
end Очищает кэш запросов для всех подключений, связанных с текущей нитью.
# File activerecord/lib/active_record/connection_handling.rb, line 323 def connected? connection_handler.connected?(connection_specification_name, role: current_role, shard: current_shard) end
Возвращает true, если Active Record подключён.
# File activerecord/lib/active_record/connection_handling.rb, line 137
def connected_to(database: nil, role: nil, shard: nil, prevent_writes: false, &blk)
if legacy_connection_handling
if self != Base
raise NotImplementedError, "`connected_to` can only be called on ActiveRecord::Base with legacy connection handling."
end
else
if self != Base && !abstract_class
raise NotImplementedError, "calling `connected_to` is only allowed on ActiveRecord::Base or abstract classes."
end
end
if database && (role || shard)
raise ArgumentError, "`connected_to` cannot accept a `database` argument with any other arguments."
elsif database
ActiveSupport::Deprecation.warn("The database key in `connected_to` is deprecated. It will be removed in Rails 6.2.0 without replacement.")
if database.is_a?(Hash)
role, database = database.first
role = role.to_sym
end
db_config, owner_name = resolve_config_for_connection(database)
handler = lookup_connection_handler(role)
handler.establish_connection(db_config, owner_name: owner_name, role: role)
with_handler(role, &blk)
elsif role || shard
unless role
raise ArgumentError, "`connected_to` cannot accept a `shard` argument without a `role`."
end
with_role_and_shard(role, shard, prevent_writes, &blk)
else
raise ArgumentError, "must provide a `shard` and/or `role`."
end
end Подключается к роли (например, запись, чтение или пользовательской роли) и/или фрагменту на период выполнения блока. По окончании блока подключение будет возвращено к исходной роли/фрагменту.
Если передан только параметр role, Active Record найдёт подключение, соответствующее запрошенной роли. Если запрошена не установленная роль, будет возбуждено исключение `ActiveRecord::ConnectionNotEstablished`:
ActiveRecord::Base.connected_to(role: :writing) do Dog.create! # creates dog using dog writing connection end ActiveRecord::Base.connected_to(role: :reading) do Dog.create! # throws exception because we're on a replica end
При переключении на фрагмент необходимо также указать роль. Если передан несуществующий фрагмент, будет возбуждено исключение `ActiveRecord::ConnectionNotEstablished`.
Если переданы фрагмент и роль, Active Record сначала найдёт роль, а затем подключение по ключу фрагмента.
ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one_replica) do Dog.first # finds first Dog record stored on the shard one replica end
Ключевое слово database устарело и будет удалено в версии 6.2.0 без замены.
# File activerecord/lib/active_record/connection_handling.rb, line 247 def connected_to?(role:, shard: ActiveRecord::Base.default_shard) current_role == role.to_sym && current_shard == shard.to_sym end
Возвращает true, если роль является текущей подключённой ролью.
ActiveRecord::Base.connected_to(role: :writing) do ActiveRecord::Base.connected_to?(role: :writing) #=> true ActiveRecord::Base.connected_to?(role: :reading) #=> false end
# File activerecord/lib/active_record/connection_handling.rb, line 188
def connected_to_many(classes, role:, shard: nil, prevent_writes: false)
if legacy_connection_handling
raise NotImplementedError, "connected_to_many is not available with legacy connection handling"
end
if self != Base || classes.include?(Base)
raise NotImplementedError, "connected_to_many can only be called on ActiveRecord::Base."
end
prevent_writes = true if role == reading_role
connected_to_stack << { role: role, shard: shard, prevent_writes: prevent_writes, klasses: classes }
yield
ensure
connected_to_stack.pop
end Подключает роль и/или фрагмент к указанным именам подключений. Опционально, `prevent_writes` может быть передано для блокировки операций записи в подключении. `reading` автоматически устанавливает `prevent_writes` в `true`.
`connected_to_many` — альтернатива вложенным блокам `connected_to`.
Пример использования:
ActiveRecord::Base.connected_to(AnimalsRecord, MealsRecord], role: :reading) do Dog.first # Read from animals replica Dinner.first # Read from meals replica Person.first # Read from primary writer end
# File activerecord/lib/active_record/connection_handling.rb, line 212
def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
if legacy_connection_handling
raise NotImplementedError, "`connecting_to` is not available with `legacy_connection_handling`."
end
prevent_writes = true if role == reading_role
self.connected_to_stack << { role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self] }
end Использование указанного подключения.
Этот метод полезен для обеспечения использования конкретного подключения. Например, при запуске консоли в режиме только для чтения.
Не рекомендуется использовать этот метод в запросе, так как он не возвращает блок, как `connected_to`.
# File activerecord/lib/active_record/connection_handling.rb, line 274 def connection retrieve_connection end
Возвращает подключение, в настоящее время связанное с классом. Также может использоваться для «заимствования» подключения для выполнения операций с базой данных, не связанных с конкретными объектами Active Record.
# File activerecord/lib/active_record/connection_handling.rb, line 298 def connection_config connection_pool.db_config.configuration_hash end
Возвращает конфигурацию связанного подключения в виде хэша:
ActiveRecord::Base.connection_config
# => {pool: 5, timeout: 5000, database: "db/development.sqlite3", adapter: "sqlite3"}
Используйте только для чтения.
# File activerecord/lib/active_record/connection_handling.rb, line 310 def connection_db_config connection_pool.db_config end
Возвращает объект db_config из связанного подключения:
ActiveRecord::Base.connection_db_config
#<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
@name="primary", @config={pool: 5, timeout: 5000, database: "db/development.sqlite3", adapter: "sqlite3"}> Используйте только для чтения.
# File activerecord/lib/active_record/connection_handling.rb, line 314 def connection_pool connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard) || raise(ConnectionNotEstablished) end
# File activerecord/lib/active_record/connection_handling.rb, line 281
def connection_specification_name
if !defined?(@connection_specification_name) || @connection_specification_name.nil?
return self == Base ? Base.name : superclass.connection_specification_name
end
@connection_specification_name
end Возвращает имя спецификации подключения из текущего класса или родительского класса.
# File activerecord/lib/active_record/connection_handling.rb, line 81
def connects_to(database: {}, shards: {})
raise NotImplementedError, "`connects_to` can only be called on ActiveRecord::Base or abstract classes" unless self == Base || abstract_class?
if database.present? && shards.present?
raise ArgumentError, "`connects_to` can only accept a `database` or `shards` argument, but not both arguments."
end
connections = []
database.each do |role, database_key|
db_config, owner_name = resolve_config_for_connection(database_key)
handler = lookup_connection_handler(role.to_sym)
connections << handler.establish_connection(db_config, owner_name: owner_name, role: role)
end
shards.each do |shard, database_keys|
database_keys.each do |role, database_key|
db_config, owner_name = resolve_config_for_connection(database_key)
handler = lookup_connection_handler(role.to_sym)
connections << handler.establish_connection(db_config, owner_name: owner_name, role: role, shard: shard.to_sym)
end
end
connections
end Подключает модель к указанным базам данных. Ключевое слово `database` принимает хэш, содержащий `adapter` и `config`.
Это создаст обработчик подключения для переключения между подключениями, найдёт хэш конфигурации по `adapter` и, наконец, установит подключение к этой конфигурации.
class AnimalsModel < ApplicationRecord
self.abstract_class = true
connects_to database: { writing: :primary, reading: :primary_replica }
end
Ключевое слово `shards` также поддерживает горизонтальное фрагментирование. API горизонтального фрагментирования также поддерживает реплики чтения. Подключите модель к списку фрагментов так:
class AnimalsModel < ApplicationRecord
self.abstract_class = true
connects_to shards: {
default: { writing: :primary, reading: :primary_replica },
shard_two: { writing: :primary_shard_two, reading: :primary_shard_replica_two }
}
end
Возвращает массив подключений к базам данных.
# File activerecord/lib/active_record/connection_handling.rb, line 49 def establish_connection(config_or_env = nil) config_or_env ||= DEFAULT_ENV.call.to_sym db_config, owner_name = resolve_config_for_connection(config_or_env) connection_handler.establish_connection(db_config, owner_name: owner_name, role: current_role, shard: current_shard) end
Устанавливает подключение к базе данных. Принимает хэш в качестве входных данных, где обязательным является ключ `adapter` с именем адаптера базы данных (в нижнем регистре), например, для обычных баз данных (MySQL, PostgreSQL и т. д.):
ActiveRecord::Base.establish_connection( adapter: "mysql2", host: "localhost", username: "myuser", password: "mypass", database: "somedatabase" )
Пример для базы данных SQLite:
ActiveRecord::Base.establish_connection( adapter: "sqlite3", database: "path/to/dbfile" )
Также принимает ключи в виде строк (например, для разбора из YAML):
ActiveRecord::Base.establish_connection( "adapter" => "sqlite3", "database" => "path/to/dbfile" )
Или URL:
ActiveRecord::Base.establish_connection( "postgres://myuser:mypass@localhost/somedatabase" )
В случае, если ActiveRecord::Base.configurations задан (Rails автоматически загружает содержимое config/database.yml в него), в качестве аргумента также может быть указан символ, представляющий ключ в хэше конфигурации:
ActiveRecord::Base.establish_connection(:production)
В случае ошибки могут быть возвращены исключения AdapterNotSpecified, AdapterNotFound и ArgumentError.
# File activerecord/lib/active_record/connection_handling.rb, line 327
def remove_connection(name = nil)
name ||= @connection_specification_name if defined?(@connection_specification_name)
# if removing a connection that has a pool, we reset the
# connection_specification_name so it will use the parent
# pool.
if connection_handler.retrieve_connection_pool(name, role: current_role, shard: current_shard)
self.connection_specification_name = nil
end
connection_handler.remove_connection_pool(name, role: current_role, shard: current_shard)
end # File activerecord/lib/active_record/connection_handling.rb, line 318 def retrieve_connection connection_handler.retrieve_connection(connection_specification_name, role: current_role, shard: current_shard) end
# File activerecord/lib/active_record/connection_handling.rb, line 233
def while_preventing_writes(enabled = true, &block)
if legacy_connection_handling
connection_handler.while_preventing_writes(enabled, &block)
else
connected_to(role: current_role, prevent_writes: enabled, &block)
end
end Блокирует запись в базу данных независимо от роли.
В некоторых случаях вам может потребоваться предотвратить запись в базу данных, даже если вы работаете с базой данных, поддерживающей запись. `while_preventing_writes` предотвратит запись в базу данных на период выполнения блока.
Этот метод не обеспечивает той же защиты, что и пользователь только для чтения, и предназначен для предотвращения случайных записей.
См. `READ_QUERY` для запросов, которые блокируются этим методом.
© 2004–2020 David Heinemeier Hansson
Licensed under the MIT License.