module ActiveRecord
Active Record — объектно-реляционное отображение в Rails
Active Record связывает классы с таблицами реляционной базы данных, создавая для приложений уровень персистентности, практически не требующий настройки. Библиотека предоставляет базовый класс, при наследовании от которого настраивается сопоставление нового класса с существующей таблицей в базе данных. В контексте приложения такие классы обычно называют моделями. Модели также можно связывать с другими моделями, определяя ассоциации.
Active Record во многом опирается на соглашения об именовании: он использует имена классов и ассоциаций для сопоставления с соответствующими таблицами базы данных и столбцами внешних ключей. Хотя эти сопоставления можно задавать явно, рекомендуется следовать соглашениям об именовании, особенно при первом знакомстве с библиотекой.
Подробнее об Active Record можно прочитать в руководстве Основы Active Record.
Краткий обзор некоторых основных возможностей:
-
Автоматическое сопоставление классов с таблицами, а атрибутов — со столбцами.
class Product < ActiveRecord::Base end
Класс Product автоматически сопоставляется с таблицей “products”, которая может выглядеть так:
CREATE TABLE products ( id bigint NOT NULL auto_increment, name varchar(255), PRIMARY KEY (id) );
При этом также будут определены следующие методы доступа:
Product#nameиProduct#name=(new_name). -
Associationsмежду объектами, задаваемые простыми методами класса.class Firm < ActiveRecord::Base has_many :clients has_one :account belongs_to :conglomerate end
-
Aggregationsобъектов-значений.class Account < ActiveRecord::Base composed_of :balance, class_name: 'Money', mapping: %w(balance amount) composed_of :address, mapping: [%w(address_street street), %w(address_city city)] end -
Правила валидации, которые могут различаться для новых и существующих объектов.
class Account < ActiveRecord::Base validates :subdomain, :name, :email_address, :password, presence: true validates :subdomain, uniqueness: true validates :terms_of_service, acceptance: true, on: :create validates :password, :email_address, confirmation: true, on: :create end
-
Callbacks, доступные на протяжении всего жизненного цикла (создание экземпляра, сохранение, удаление, валидация и т. д.).class Person < ActiveRecord::Base before_destroy :invalidate_payment_plan # the `invalidate_payment_plan` method gets called just before Person#destroy end
-
Inheritanceклассов.class Company < ActiveRecord::Base; end class Firm < Company; end class Client < Company; end class PriorityClient < Client; end
-
# Database transaction Account.transaction do david.withdrawal(100) mary.deposit(100) end
-
Рефлексия столбцов, ассоциаций и агрегатов.
reflection = Firm.reflect_on_association(:clients) reflection.klass # => Client (class) Firm.columns # Returns an array of column descriptors for the firms table
-
Абстрагирование от базы данных с помощью простых адаптеров.
# connect to SQLite3 ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'dbfile.sqlite3') # connect to MySQL with authentication ActiveRecord::Base.establish_connection( adapter: 'mysql2', host: 'localhost', username: 'me', password: 'secret', database: 'activerecord' )
Подробнее и узнайте о встроенной поддержке MySQL, PostgreSQL и SQLite3.
-
Поддержка ведения журналов с помощью Log4r и Logger.
ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT) ActiveRecord::Base.logger = Log4r::Logger.new('Application Log') -
Не зависящее от СУБД управление схемой с помощью миграций.
class AddSystemSettings < ActiveRecord::Migration[8.1] def up create_table :system_settings do |t| t.string :name t.string :label t.text :value t.string :type t.integer :position end SystemSetting.create name: 'notice', label: 'Use notice?', value: 1 end def down drop_table :system_settings end end
Философия
Active Record — это реализация шаблона объектно-реляционного отображения (ORM) под тем же названием, описанного Мартином Фаулером:
«Объект, который оборачивает строку таблицы или представления базы данных, инкапсулирует доступ к базе данных и добавляет к этим данным логику предметной области».
Active Record стремится предоставить согласованную оболочку, решающую неудобства объектно-реляционного отображения. Главный принцип этого отображения — свести к минимуму количество кода, необходимого для создания модели предметной области реального мира. Это достигается благодаря ряду соглашений, позволяющих Active Record выводить сложные связи и структуры на основе минимального количества явных указаний.
Соглашения вместо конфигурации:
-
Никаких XML-файлов!
-
Широкое использование рефлексии и расширения во время выполнения
-
Магия — не обязательно плохое слово
Признавайте роль базы данных:
-
В нестандартных случаях и ради производительности можно перейти к SQL
-
Не пытается дублировать или заменять определения данных
Загрузка и установка
Последнюю версию Active Record можно установить с помощью RubyGems:
$ gem install activerecord
Исходный код можно скачать в составе проекта Rails на GitHub:
Лицензия
Active Record распространяется по лицензии MIT:
Поддержка
Документация API доступна по адресу:
Сообщения об ошибках в проекте Ruby on Rails можно отправлять здесь:
Предложения по новым функциям следует обсуждать на форуме rubyonrails-core:
Класс ошибки валидации для обёртывания ошибок связанных записей с поддержкой index_errors.
Константы
- MigrationProxy
-
MigrationProxyиспользуется, чтобы отложить загрузку фактических классов миграций до момента, когда они понадобятся - Point
- UnknownAttributeError
-
Active Model UnknownAttributeError
Возникает, когда при массовом присваивании передаются неизвестные атрибуты.
class Person include ActiveModel::AttributeAssignment include ActiveModel::Validations end person = Person.new person.assign_attributes(name: 'Gorby') # => ActiveModel::UnknownAttributeError: unknown attribute 'name' for Person.
Атрибуты
Публичные методы класса
# File activerecord/lib/active_record.rb, line 370 singleton_class.attr_accessor :action_on_strict_loading_violation
Настройте приложение так, чтобы при нарушении ассоциацией строгой загрузки оно записывало сообщение в журнал или вызывало исключение. По умолчанию используется :raise.
# File activerecord/lib/active_record.rb, line 573
def self.after_all_transactions_commit(&block)
open_transactions = all_open_transactions
if open_transactions.empty?
yield
elsif open_transactions.size == 1
open_transactions.first.after_commit(&block)
else
count = open_transactions.size
callback = -> do
count -= 1
block.call if count.zero?
end
open_transactions.each do |t|
t.after_commit(&callback)
end
open_transactions = nil # rubocop:disable Lint/UselessAssignment avoid holding it in the closure
end
end Регистрирует блок, который будет вызван после фиксации всех текущих транзакций.
Если в данный момент нет открытых транзакций, блок вызывается немедленно.
Если открыто несколько вложенных транзакций, блок вызывается после фиксации самой внешней транзакции.
Если какая-либо из открытых транзакций будет отменена, блок не будет вызван.
Если несколько транзакций открыты в нескольких базах данных, блок будет вызван, когда все они будут зафиксированы. Однако учтите, что вложенные транзакции в двух разных базах данных — это антипаттерн шардинга, который чреват множеством проблем.
# File activerecord/lib/active_record.rb, line 288 singleton_class.attr_accessor :async_query_executor
Задаёт async_query_executor для приложения. По умолчанию используется исполнитель с пулом потоков, заданный как nil, который не выполняет запросы в фоновом режиме. Для использования этой возможности приложение должно настроить исполнитель с пулом потоков. Доступны следующие варианты:
* nil - Does not initialize a thread pool executor. Any async calls will be run in the foreground. * :global_thread_pool - Initializes a single +Concurrent::ThreadPoolExecutor+ that uses the +async_query_concurrency+ for the +max_threads+ value. * :multi_thread_pool - Initializes a +Concurrent::ThreadPoolExecutor+ for each database connection. The initializer values are defined in the configuration hash.
# File activerecord/lib/active_record.rb, line 235 singleton_class.attr_reader :db_warnings_action
Действие, которое следует выполнить, если запрос к базе данных выдаёт предупреждение. Должно быть одним из значений :ignore, :log, :raise, :report или пользовательским proc. По умолчанию используется :ignore.
# File activerecord/lib/active_record.rb, line 237
def self.db_warnings_action=(action)
@db_warnings_action =
case action
when :ignore
nil
when :log
->(warning) do
warning_message = "[#{warning.class}] #{warning.message}"
warning_message += " (#{warning.code})" if warning.code
ActiveRecord::Base.logger.warn(warning_message)
end
when :raise
->(warning) { raise warning }
when :report
->(warning) { Rails.error.report(warning, handled: true) }
when Proc
action
else
raise ArgumentError, "db_warnings_action must be one of :ignore, :log, :raise, :report, or a custom proc."
end
end # File activerecord/lib/active_record.rb, line 267 singleton_class.attr_accessor :db_warnings_ignore
Задаёт список разрешённых предупреждений базы данных. Это может быть строка, регулярное выражение или код ошибки базы данных.
ActiveRecord::Base.db_warnings_ignore = [/`SHOW WARNINGS` did not return the warnings/, "01000"]
# File activerecord/lib/active_record.rb, line 220
def self.default_timezone=(default_timezone)
unless %i(local utc).include?(default_timezone)
raise ArgumentError, "default_timezone must be either :utc (default) or :local."
end
@default_timezone = default_timezone
end Определяет, использовать ли Time.utc (с :utc) или Time.local (с :local) при извлечении дат и времени из базы данных. По умолчанию задано значение :utc.
# File activerecord/lib/active_record.rb, line 495
def self.deprecated_associations_options
{
mode: ActiveRecord::Associations::Deprecation.mode,
backtrace: ActiveRecord::Associations::Deprecation.backtrace
}
end # File activerecord/lib/active_record.rb, line 479
def self.deprecated_associations_options=(options)
raise ArgumentError, "deprecated_associations_options must be a hash" unless options.is_a?(Hash)
valid_keys = [:mode, :backtrace]
invalid_keys = options.keys - valid_keys
unless invalid_keys.empty?
inflected_key = invalid_keys.size == 1 ? "key" : "keys"
raise ArgumentError, "invalid deprecated_associations_options #{inflected_key} #{invalid_keys.map(&:inspect).to_sentence} (valid keys are #{valid_keys.map(&:inspect).to_sentence})"
end
options.each do |key, value|
ActiveRecord::Associations::Deprecation.send("#{key}=", value)
end
end # File activerecord/lib/active_record.rb, line 556 def self.disconnect_all! ConnectionAdapters::PoolConfig.disconnect_all! end
Явно закрывает все подключения к базам данных во всех пулах.
# File activerecord/lib/active_record.rb, line 425 singleton_class.attr_accessor :dump_schema_after_migration
Указывает, следует ли выполнять дамп схемы в конце команды bin/rails db:migrate. По умолчанию задано значение true, что удобно в среде разработки. В идеале в производственной среде это значение должно быть false, поскольку дамп схемы там требуется редко.
# File activerecord/lib/active_record.rb, line 435 singleton_class.attr_accessor :dump_schemas
Указывает, какие схемы базы данных следует выгружать при вызове db:schema:dump. Если значение равно :schema_search_path (по умолчанию), выгружаются все схемы, перечисленные в schema_search_path. Используйте :all, чтобы выгрузить все схемы независимо от schema_search_path, или строку со списком схем, разделённых запятыми, чтобы задать собственный список.
# File activerecord/lib/active_record.rb, line 545 def self.eager_load! super ActiveRecord::Locking.eager_load! ActiveRecord::Scoping.eager_load! ActiveRecord::Associations.eager_load! ActiveRecord::AttributeMethods.eager_load! ActiveRecord::ConnectionAdapters.eager_load! ActiveRecord::Encryption.eager_load! end
# File activerecord/lib/active_record.rb, line 390 singleton_class.attr_accessor :error_on_ignored_order
Указывает, следует ли вызывать ошибку, если при пакетной обработке запрос игнорирует сортировку. Это полезно в приложениях, где игнорирование области видимости должно считаться ошибкой, а не просто предупреждением.
# File activerecord/lib/active_record/gem_version.rb, line 5 def self.gem_version Gem::Version.new VERSION::STRING end
Возвращает текущую загруженную версию Active Record в виде Gem::Version.
# File activerecord/lib/active_record.rb, line 476 singleton_class.attr_accessor :generate_secure_token_on
Управляет моментом создания значения для объявлений has_secure_token. По умолчанию используется :create.
# File activerecord/lib/active_record.rb, line 304
def self.global_executor_concurrency=(global_executor_concurrency)
if self.async_query_executor.nil? || self.async_query_executor == :multi_thread_pool
raise ArgumentError, "`global_executor_concurrency` cannot be set when the executor is nil or set to `:multi_thread_pool`. For multiple thread pools, please set the concurrency in your database configuration."
end
@global_executor_concurrency = global_executor_concurrency
end Задаёт global_executor_concurrency. Это значение конфигурации можно использовать только с асинхронным исполнителем запросов на основе глобального пула потоков.
# File activerecord/lib/active_record.rb, line 191 singleton_class.attr_accessor :lazily_load_schema_cache
Загружает кэш схемы отложенно. Эта настройка позволяет загружать кэш схемы при установлении подключения, а не во время запуска.
# File activerecord/lib/active_record.rb, line 502 def self.marshalling_format_version Marshalling.format_version end
# File activerecord/lib/active_record.rb, line 506 def self.marshalling_format_version=(value) Marshalling.format_version = value end
# File activerecord/lib/active_record.rb, line 543 singleton_class.attr_accessor :message_verifiers
Экземпляр ActiveSupport::MessageVerifiers для Active Record. Если используется Rails, здесь будет задано значение Rails.application.message_verifiers.
# File activerecord/lib/active_record.rb, line 410 singleton_class.attr_accessor :migration_strategy
Задаёт стратегию выполнения миграций.
# File activerecord/lib/active_record.rb, line 320
def self.permanent_connection_checkout=(value)
unless [true, :deprecated, :disallowed].include?(value)
raise ArgumentError, "permanent_connection_checkout must be one of: `true`, `:deprecated` or `:disallowed`"
end
@permanent_connection_checkout = value
end Определяет, разрешён ли ActiveRecord::Base.connection, помечен ли он как устаревший или полностью запрещён.
# File activerecord/lib/active_record.rb, line 529 singleton_class.attr_accessor :protocol_adapters
Сопоставляет протоколы баз данных/СУБД с используемыми адаптерами баз данных. Это используется только переменной окружения DATABASE_URL.
Пример
DATABASE_URL="mysql://myuser:mypass@localhost/somedatabase"
Указанный выше URL задаёт MySQL в качестве желаемого протокола/СУБД, после чего конфигурация приложения может определить, какой адаптер использовать. В этом примере по умолчанию mysql сопоставляется с mysql2, но также поддерживается :trilogy.
ActiveRecord.protocol_adapters.mysql = "mysql2"
Названия протоколов произвольны; здесь можно зарегистрировать и задать внешние адаптеры баз данных.
# File activerecord/lib/active_record.rb, line 342 singleton_class.attr_accessor :queues
Задаёт названия очередей, используемых фоновыми заданиями.
# File activerecord/lib/active_record.rb, line 462 singleton_class.attr_accessor :raise_int_wider_than_64bit
Настраиваемый параметр приложения типа boolean, определяющий, следует ли вызывать исключение, если PostgreSQLAdapter получает целое число, размер которого превышает знаковое 64-битное представление.
# File activerecord/lib/active_record.rb, line 207
def self.schema_cache_ignored_table?(table_name)
ActiveRecord.schema_cache_ignored_tables.any? do |ignored|
ignored === table_name
end
end Проверяет, игнорируется ли table_name, сверяя его со значением параметра schema_cache_ignored_tables.
ActiveRecord.schema_cache_ignored_table?(:developers)
# File activerecord/lib/active_record.rb, line 199 singleton_class.attr_accessor :schema_cache_ignored_tables
Список таблиц или регулярных выражений для отбора таблиц, которые следует игнорировать при создании дампа кэша схемы. Например, если задано значение +[/^_/]+, в дамп кэша схемы не попадут таблицы, названия которых начинаются с подчёркивания.
# File activerecord/lib/active_record.rb, line 382 singleton_class.attr_accessor :schema_format
Задаёт формат дампа схемы базы данных с помощью Rakefile Rails. Если указано :sql, схема выгружается в виде операторов SQL (возможно, специфичных для конкретной базы данных). Если указано :ruby, схема выгружается в файл ActiveRecord::Schema, который можно загрузить в любую базу данных, поддерживающую миграции. Используйте :ruby, если в средах разработки и тестирования нужны разные адаптеры баз данных. Это значение можно переопределить для каждой базы данных в её конфигурации.
# File activerecord/lib/active_record.rb, line 416 singleton_class.attr_accessor :schema_versions_formatter
Задаёт средство форматирования, используемое дампером схемы для форматирования информации о версиях.
# File activerecord/lib/active_record.rb, line 396 singleton_class.attr_accessor :timestamped_migrations
Указывает, следует ли использовать временные метки для версий миграций.
# File activerecord/lib/active_record.rb, line 454 singleton_class.attr_accessor :use_yaml_unsafe_load
Настраиваемый параметр приложения типа boolean, который указывает YAML Coder использовать небезопасную загрузку, если задано значение true.
# File activerecord/lib/active_record.rb, line 404 singleton_class.attr_accessor :validate_migration_timestamps
Указывает, следует ли проверять временные метки миграций. Если параметр включён, будет вызвана ошибка, если временная метка опережает метку текущего времени более чем на один день. Параметр timestamped_migrations должен иметь значение true.
# File activerecord/lib/active_record.rb, line 335 singleton_class.attr_accessor :verbose_query_logs
Указывает, следует ли записывать в журнал методы, вызвавшие запросы к базе данных, под соответствующими запросами. По умолчанию задано значение false.
# File activerecord/lib/active_record.rb, line 444 singleton_class.attr_accessor :verify_foreign_keys_for_fixtures
Если задано значение true, Rails проверит все внешние ключи в базе данных после загрузки фикстур. Если обнаружатся нарушения внешних ключей, будет вызвана ошибка, указывающая на некорректно написанные фикстуры. Поддерживается PostgreSQL и SQLite.
# File activerecord/lib/active_record/version.rb, line 7 def self.version gem_version end
Возвращает текущую загруженную версию Active Record в виде Gem::Version.
# File activerecord/lib/active_record.rb, line 616 def self.with_transaction_isolation_level(isolation_level, &block) original_level = self.default_transaction_isolation_level self.default_transaction_isolation_level = isolation_level yield ensure self.default_transaction_isolation_level = original_level end
Задаёт уровень изоляции транзакций для всех пулов подключений внутри блока.
# File activerecord/lib/active_record.rb, line 469 singleton_class.attr_accessor :yaml_column_permitted_classes
Настраиваемый массив приложения, содержащий дополнительные классы, разрешённые для Psych safe_load в YAML Coder.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.