Spec-Zone.ru › Ruby on Rails 8.1

module ActiveRecord::ConnectionHandling

Подключение Active Record

Константы

DEFAULT_ENV
RAILS_ENV

Атрибуты

connection_specification_name [W]

Открытые методы экземпляра

clear_query_caches_for_current_thread () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 261
def clear_query_caches_for_current_thread
  connection_handler.each_connection_pool do |pool|
    pool.clear_query_cache
  end
end

Очищает кэш запросов для всех подключений, связанных с текущим потоком.

connected? () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 354
def connected?
  connection_handler.connected?(connection_specification_name, role: current_role, shard: current_shard)
end

Возвращает true, если Active Record подключён.

connected_to (role: nil, shard: nil, prevent_writes: false, &blk) Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 137
def connected_to(role: nil, shard: nil, prevent_writes: false, &blk)
  if self != Base && !abstract_class
    raise NotImplementedError, "calling `connected_to` is only allowed on ActiveRecord::Base or abstract classes."
  end

  if !connection_class? && !primary_class?
    raise NotImplementedError, "calling `connected_to` is only allowed on the abstract class that established the connection."
  end

  unless role || shard
    raise ArgumentError, "must provide a `shard` and/or `role`."
  end

  with_role_and_shard(role, shard, prevent_writes, &blk)
end

На время выполнения блока подключается к роли (например, для записи, чтения или пользовательской роли) и/или шарду. По завершении блока подключение возвращается к исходной роли / шарду.

Если передана только роль, 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
connected_to? (role:, shard: ActiveRecord::Base.default_shard) Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 256
def connected_to?(role:, shard: ActiveRecord::Base.default_shard)
  current_role == role.to_sym && current_shard == shard.to_sym
end

Возвращает true, если role — это текущая подключённая роль и/или текущий подключённый шард. Если шард не передан, используется значение по умолчанию.

ActiveRecord::Base.connected_to(role: :writing) do
  ActiveRecord::Base.connected_to?(role: :writing) #=> true
  ActiveRecord::Base.connected_to?(role: :reading) #=> false
end

ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one) do
  ActiveRecord::Base.connected_to?(role: :reading, shard: :shard_one) #=> true
  ActiveRecord::Base.connected_to?(role: :reading, shard: :default) #=> false
  ActiveRecord::Base.connected_to?(role: :writing, shard: :shard_one) #=> true
end
connected_to_all_shards (role: nil, prevent_writes: false, &blk) Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 189
def connected_to_all_shards(role: nil, prevent_writes: false, &blk)
  shard_keys.map do |shard|
    connected_to(shard: shard, role: role, prevent_writes: prevent_writes, &blk)
  end
end

Передаёт блок в connected_to для каждого shard, к которому настроено подключение модели (если такие есть), и возвращает результаты в массиве.

При необходимости можно передать role и/или prevent_writes; они будут переданы в каждый вызов connected_to.

connected_to_many (*classes, role:, shard: nil, prevent_writes: false) { || ... } Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 166
def connected_to_many(*classes, role:, shard: nil, prevent_writes: false)
  classes = classes.flatten

  if self != Base || classes.include?(Base)
    raise NotImplementedError, "connected_to_many can only be called on ActiveRecord::Base."
  end

  prevent_writes = true if role == ActiveRecord.reading_role

  append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: classes)
  begin
    yield
  ensure
    connected_to_stack.pop
  end
end

Подключает роль и/или шард к указанным именам подключений. При необходимости можно передать prevent_writes, чтобы запретить запись в подключение. reading автоматически установит prevent_writes в значение true.

connected_to_many — альтернатива глубоко вложенным блокам connected_to.

Пример использования:

ActiveRecord::Base.connected_to_many(AnimalsRecord, MealsRecord, role: :reading) do
  Dog.first # Read from animals replica
  Dinner.first # Read from meals replica
  Person.first # Read from primary writer
end
connecting_to (role: default_role, shard: default_shard, prevent_writes: false) Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 202
def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
  prevent_writes = true if role == ActiveRecord.reading_role

  append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
end

Использует указанное подключение.

Этот метод полезен, когда необходимо гарантировать использование определённого подключения. Например, при запуске консоли в режиме только для чтения.

Не рекомендуется использовать этот метод в запросе, поскольку он, в отличие от connected_to, не принимает блок.

connection () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 277
    def connection
      pool = connection_pool
      if pool.permanent_lease?
        case ActiveRecord.permanent_connection_checkout
        when :deprecated
          ActiveRecord.deprecator.warn <<~MESSAGE
            Called deprecated `ActiveRecord::Base.connection` method.

            Either use `with_connection` or `lease_connection`.
          MESSAGE
        when :disallowed
          raise ActiveRecordError, <<~MESSAGE
            Called deprecated `ActiveRecord::Base.connection` method.

            Either use `with_connection` or `lease_connection`.
          MESSAGE
        end
        pool.lease_connection
      else
        pool.active_connection
      end
    end

Устаревший метод с мягким переходом. Вместо него используйте with_connection или lease_connection.

connection_db_config () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 337
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: "storage/development.sqlite3", adapter: "sqlite3"}>

Используйте только для чтения.

connection_pool () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 345
def connection_pool
  connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard, strict: true)
end
connection_specification_name () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 319
def connection_specification_name
  if @connection_specification_name.nil?
    return self == Base ? Base.name : superclass.connection_specification_name
  end
  @connection_specification_name
end

Возвращает имя спецификации подключения текущего класса или его родителя.

connects_to (database: {}, shards: {}) Показать исходный код
# 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 = []

  @shard_keys = shards.keys

  if shards.empty?
    shards[:default] = database
  end

  self.default_shard = shards.keys.first

  shards.each do |shard, database_keys|
    database_keys.each do |role, database_key|
      db_config = resolve_config_for_connection(database_key)

      self.connection_class = true
      shard = shard.to_sym unless shard.is_a? Integer
      connections << connection_handler.establish_connection(db_config, owner_name: self, role: role, shard: shard)
    end
  end

  connections
end

Подключает модель к указанным базам данных. Ключевое слово database принимает хеш, состоящий из role и database_key.

Метод ищет конфигурацию базы данных с помощью database_key и устанавливает подключение к этой конфигурации.

class AnimalsModel < ApplicationRecord
  self.abstract_class = true

  connects_to database: { writing: :primary, reading: :primary_replica }
end

connects_to также поддерживает горизонтальное шардирование. 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

Возвращает массив подключений к базам данных.

establish_connection (config_or_env = nil) Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 50
def establish_connection(config_or_env = nil)
  config_or_env ||= DEFAULT_ENV.call.to_sym
  db_config = resolve_config_for_connection(config_or_env)
  connection_handler.establish_connection(db_config, owner_name: self, 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.

lease_connection () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 272
def lease_connection
  connection_pool.lease_connection
end

Возвращает подключение, связанное с классом в данный момент. Его также можно использовать, чтобы «одолжить» подключение для работы с базой данных, не связанной с конкретными объектами Active Record. Подключение останется занятым до конца запроса или задания либо до вызова release_connection.

prohibit_shard_swapping (enabled = true) { || ... } Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 214
def prohibit_shard_swapping(enabled = true)
  prev_value = ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping]
  ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = enabled
  yield
ensure
  ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = prev_value
end

Запрещает переключение шардов во время выполнения переданного блока.

В некоторых случаях может потребоваться разрешить переключение шардов, но запретить вложенным вызовам connected_to или connected_to_many переключать их повторно. Это полезно, если шардирование используется для изоляции базы данных на уровне отдельных запросов.

release_connection () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 301
def release_connection
  connection_pool.release_connection
end

Возвращает текущее занятое подключение в пул.

remove_connection () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 358
def remove_connection
  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
retrieve_connection () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 349
def retrieve_connection
  connection_handler.retrieve_connection(connection_specification_name, role: current_role, shard: current_shard)
end
shard_keys () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 379
def shard_keys
  connection_class_for_self.instance_variable_get(:@shard_keys) || []
end
shard_swapping_prohibited? () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 223
def shard_swapping_prohibited?
  ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping]
end

Определяет, запрещено ли в данный момент переключение шардов.

sharded? () Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 383
def sharded?
  shard_keys.any?
end
while_preventing_writes (enabled = true, &block) Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 238
def while_preventing_writes(enabled = true, &block)
  connected_to(role: current_role, prevent_writes: enabled, &block)
end

Запрещает запись в базу данных независимо от роли.

В некоторых случаях может потребоваться запретить запись в базу данных, даже если используется база данных, поддерживающая запись. while_preventing_writes запрещает запись в базу данных на время выполнения блока.

Этот метод не обеспечивает такую же защиту, как пользователь с доступом только для чтения, и предназначен для предотвращения случайной записи.

Список запросов, блокируемых этим методом, см. в READ_QUERY.

with_connection (prevent_permanent_checkout: false, &block) Показать исходный код
# File activerecord/lib/active_record/connection_handling.rb, line 312
def with_connection(prevent_permanent_checkout: false, &block)
  connection_pool.with_connection(prevent_permanent_checkout: prevent_permanent_checkout, &block)
end

Получает подключение из пула, передаёт его блоку, а затем возвращает в пул. Если подключение уже было занято через lease_connection или родительский вызов with_connection, блоку передаётся то же подключение. Если внутри блока вызывается lease_connection, подключение не будет возвращено в пул. Если внутри блока вызывается connection, подключение не будет возвращено в пул, если только аргумент prevent_permanent_checkout не установлен в true.

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API