модуль ActiveRecord::Core
Ядро Active Record
Атрибуты
Открытые методы класса
# File activerecord/lib/active_record/core.rb, line 119 class_attribute :attributes_for_inspect, instance_accessor: false, default: :all
Указывает атрибуты, которые будут включены в вывод метода inspect:
Post.attributes_for_inspect = [:id, :title] Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!">"
При значении ‘:all’ метод inspect будет отображать все атрибуты записи:
Post.attributes_for_inspect = :all Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
# File activerecord/lib/active_record/core.rb, line 77 def self.configurations @@configurations end
Возвращает полностью разрешённый объект ActiveRecord::DatabaseConfigurations.
# File activerecord/lib/active_record/core.rb, line 71 def self.configurations=(config) @@configurations = ActiveRecord::DatabaseConfigurations.new(config) end
Содержит конфигурацию базы данных — как обычно хранится в config/database.yml — в виде объекта ActiveRecord::DatabaseConfigurations.
Например, следующий файл database.yml…
development: adapter: sqlite3 database: storage/development.sqlite3 production: adapter: sqlite3 database: storage/production.sqlite3
…приведёт к тому, что ActiveRecord::Base.configurations будет выглядеть так:
#<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
#<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
@name="primary", @config={adapter: "sqlite3", database: "storage/development.sqlite3"}>,
#<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
@name="primary", @config={adapter: "sqlite3", database: "storage/production.sqlite3"}>
]> # File activerecord/lib/active_record/core.rb, line 133 def self.connection_handler ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] || default_connection_handler end
# File activerecord/lib/active_record/core.rb, line 137 def self.connection_handler=(handler) ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] = handler end
# File activerecord/lib/active_record/core.rb, line 196
def self.current_preventing_writes
connected_to_stack.reverse_each do |hash|
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_class_for_self)
end
false
end Возвращает символ, представляющий текущее значение для предотвращения записи.
ActiveRecord::Base.connected_to(role: :reading) do ActiveRecord::Base.current_preventing_writes #=> true end ActiveRecord::Base.connected_to(role: :writing) do ActiveRecord::Base.current_preventing_writes #=> false end
# File activerecord/lib/active_record/core.rb, line 159
def self.current_role
connected_to_stack.reverse_each do |hash|
return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
return hash[:role] if hash[:role] && hash[:klasses].include?(connection_class_for_self)
end
default_role
end Возвращает символ, представляющий текущую подключённую роль.
ActiveRecord::Base.connected_to(role: :writing) do ActiveRecord::Base.current_role #=> :writing end ActiveRecord::Base.connected_to(role: :reading) do ActiveRecord::Base.current_role #=> :reading end
# File activerecord/lib/active_record/core.rb, line 177
def self.current_shard
connected_to_stack.reverse_each do |hash|
return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_class_for_self)
end
default_shard
end Возвращает символ, представляющий текущий подключённый фрагмент.
ActiveRecord::Base.connected_to(role: :reading) do ActiveRecord::Base.current_shard #=> :default end ActiveRecord::Base.connected_to(role: :writing, shard: :one) do ActiveRecord::Base.current_shard #=> :one end
# File activerecord/lib/active_record/core.rb, line 47 class_attribute :destroy_association_async_batch_size, instance_writer: false, instance_predicate: false, default: nil
Указывает максимальное количество записей, которые будут удалены в одной задаче фонового выполнения опцией dependent: :destroy_async. При значении nil (по умолчанию) все зависимые записи будут удалены в одной задаче фонового выполнения. Если указано значение, записи, подлежащие удалению, будут разделены на несколько задач фонового выполнения.
# File activerecord/lib/active_record/core.rb, line 27
def self.destroy_association_async_job
if _destroy_association_async_job.is_a?(String)
self._destroy_association_async_job = _destroy_association_async_job.constantize
end
_destroy_association_async_job
rescue NameError => error
raise NameError, "Unable to load destroy_association_async_job: #{error.message}"
end Класс задачи, используемый для удаления ассоциаций в фоновом режиме.
# File activerecord/lib/active_record/core.rb, line 87 class_attribute :enumerate_columns_in_select_statements, instance_accessor: false, default: false
Вынужденное перечисление всех столбцов в операторах SELECT. Например, SELECT first_name, last_name FROM ... вместо SELECT * FROM .... Это предотвращает ошибки PreparedStatementCacheExpired, когда столбец добавляется в базу данных во время работы приложения.
# File activerecord/lib/active_record/core.rb, line 22 class_attribute :logger, instance_writer: false
Принимает логгер, соответствующий интерфейсу Log4r или по умолчанию класс Ruby Logger, который затем передаётся в любые новые подключения к базе данных. Этот логгер можно получить, вызвав logger для класса модели Active Record или экземпляра модели Active Record.
# File activerecord/lib/active_record/core.rb, line 460 def initialize(attributes = nil) @new_record = true @attributes = self.class._default_attributes.deep_dup init_internals initialize_internals_callback super yield self if block_given? _run_initialize_callbacks end
Новые объекты могут быть созданы пустыми (не передавать параметры построения) или предварительно заполненными атрибутами, но ещё не сохранёнными (передать хеш с именами ключей, соответствующими именам столбцов связанной таблицы). В обоих случаях допустимые ключи атрибутов определяются именами столбцов связанной таблицы — поэтому атрибуты, которые не являются частью столбцов таблицы, недопустимы.
Пример
# Instantiates a single new object User.new(first_name: 'Jamie')
Общедоступные методы экземпляра
# File activerecord/lib/active_record/core.rb, line 654
def <=>(other_object)
if other_object.is_a?(self.class)
to_key <=> other_object.to_key
else
super
end
end Разрешает сортировку по объектам
# File activerecord/lib/active_record/core.rb, line 620
def ==(comparison_object)
super ||
comparison_object.instance_of?(self.class) &&
primary_key_values_present? &&
comparison_object.id == id
end Возвращает true, если comparison_object — это тот же самый объект, или comparison_object — того же типа и self имеет ID, равный comparison_object.id.
Обратите внимание, что новые записи по определению отличаются от любых других записей, если только другая запись не является самим получателем. Кроме того, если вы загружаете существующие записи с select и опускаете ID, вы делаете это на свой страх и риск; этот предикат вернёт false.
Обратите также внимание, что удаление записи сохраняет её ID в экземпляре модели, поэтому удалённые модели по-прежнему сравнимы.
# File activerecord/lib/active_record/core.rb, line 512
Идентично методу clone в Ruby. Это «неглубокая» копия. Будьте осторожны, ваши атрибуты не копируются. Это означает, что изменение атрибутов клона изменит оригинал, поскольку оба будут указывать на тот же хеш атрибутов. Если вам нужна копия вашего хеша атрибутов, пожалуйста, используйте метод dup.
user = User.first new_user = user.clone user.name # => "Bob" new_user.name = "Joe" user.name # => "Joe" user.object_id == new_user.object_id # => false user.name.object_id == new_user.name.object_id # => true user.name.object_id == user.dup.name.object_id # => false
# File activerecord/lib/active_record/core.rb, line 739 def connection_handler self.class.connection_handler end
# File activerecord/lib/active_record/core.rb, line 529
Дублированные объекты не имеют назначенного идентификатора и обрабатываются как новые записи. Обратите внимание, что это «неглубокая» копия, так как она копирует только атрибуты объекта, а не его ассоциации. Объем «глубокой» копии зависит от приложения и поэтому предоставляется на реализацию приложением в соответствии с его потребностями. Метод dup не сохраняет временные метки (created|updated)_(at|on) и столбец блокировки.
# File activerecord/lib/active_record/core.rb, line 576 def encode_with(coder) self.class.yaml_encoder.encode(@attributes, coder) coder["new_record"] = new_record? coder["active_record_yaml_version"] = 2 end
Заполните coder атрибутами этой записи, которые должны быть сериализованы. Структура coder , определённая в этом методе, гарантированно соответствует структуре coder , переданной методу init_with.
Пример:
class Post < ActiveRecord::Base
end
coder = {}
Post.new.encode_with(coder)
coder # => {"attributes" => {"id" => nil, ... }}
# File activerecord/lib/active_record/core.rb, line 643 def freeze @attributes = @attributes.clone.freeze self end
Клонирует и замораживает хеш атрибутов, так что ассоциации по-прежнему доступны, даже для удалённых записей, но клонированные модели не будут заморожены.
# File activerecord/lib/active_record/core.rb, line 649 def frozen? @attributes.frozen? end
Возвращает true, если хеш атрибутов был заморожен.
# File activerecord/lib/active_record/core.rb, line 763 def full_inspect inspect_with_attributes(all_attributes_for_inspect) end
Возвращает все атрибуты записи в виде отформатированной строки, игнорируя .attributes_for_inspect.
Post.first.full_inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
# File activerecord/lib/active_record/core.rb, line 630
def hash
id = self.id
if primary_key_values_present?
self.class.hash ^ id.hash
else
super
end
end Делегирует к id, чтобы две записи одного типа и id могли работать с чем-то вроде:
[ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
# File activerecord/lib/active_record/core.rb, line 487 def init_with(coder, &block) coder = LegacyYamlAdapter.convert(coder) attributes = self.class.yaml_encoder.decode(coder) init_with_attributes(attributes, coder["new_record"], &block) end
Инициализирует пустой объект модели из coder. coder должен быть результатом предыдущего кодирования модели Active Record, используя encode_with.
class Post < ActiveRecord::Base
end
old_post = Post.new(title: "hello world")
coder = {}
old_post.encode_with(coder)
post = Post.allocate
post.init_with(coder)
post.title # => 'hello world'
# File activerecord/lib/active_record/core.rb, line 753 def inspect inspect_with_attributes(attributes_for_inspect) end
Возвращает атрибуты записи в виде отформатированной строки.
Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
Атрибуты можно ограничить, установив .attributes_for_inspect.
Post.attributes_for_inspect = [:id, :title] Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!">"
# File activerecord/lib/active_record/core.rb, line 769
def pretty_print(pp)
return super if custom_inspect_method_defined?
pp.object_address_group(self) do
if @attributes
attr_names = attributes_for_inspect.select { |name| _has_attribute?(name.to_s) }
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
attr_name = attr_name.to_s
pp.breakable " "
pp.group(1) do
pp.text attr_name
pp.text ":"
pp.breakable
value = attribute_for_inspect(attr_name)
pp.text value
end
end
else
pp.breakable " "
pp.text "not initialized"
end
end
end Принимает PP и красиво выводит эту запись в него, позволяя получить хороший результат из pp record при необходимости pp.
# File activerecord/lib/active_record/core.rb, line 735 def readonly! @readonly = true end
Помечает эту запись как только для чтения.
customer = Customer.first customer.readonly! customer.save # Raises an ActiveRecord::ReadOnlyRecord
# File activerecord/lib/active_record/core.rb, line 671 def readonly? @readonly end
Возвращает true, если запись только для чтения.
# File activerecord/lib/active_record/core.rb, line 583
Возвращает хеш заданных методов с их именами в качестве ключей и возвращаемыми значениями в качестве значений.
topic = Topic.new(title: "Budget", author_name: "Jason")
topic.slice(:title, :author_name)
=> { "title" => "Budget", "author_name" => "Jason" } # File activerecord/lib/active_record/core.rb, line 709
def strict_loading!(value = true, mode: :all)
unless [:all, :n_plus_one_only].include?(mode)
raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only] but #{mode.inspect} was provided."
end
@strict_loading_mode = mode
@strict_loading = value
end Устанавливает режим strict_loading для записи. Это вызовет ошибку, если запись попытается лениво загрузить ассоциацию.
user = User.first user.strict_loading! # => true user.address.city => ActiveRecord::StrictLoadingViolationError user.comments.to_a => ActiveRecord::StrictLoadingViolationError
Параметры
-
value— булево значение, указывающее на включение или отключение строгой загрузки. -
:mode—Symbol, указывающий режим строгой загрузки. По умолчанию :all. Использование режима :n_plus_one_only вызовет ошибку только в случае ленивой загрузки ассоциации, которая приведёт к запросу n + один.
Примеры
user = User.first user.strict_loading!(false) # => false user.address.city # => "Tatooine" user.comments.to_a # => [#<Comment:0x00...] user.strict_loading!(mode: :n_plus_one_only) user.address.city # => "Tatooine" user.comments.to_a # => [#<Comment:0x00...] user.comments.first.ratings.to_a => ActiveRecord::StrictLoadingViolationError
# File activerecord/lib/active_record/core.rb, line 676 def strict_loading? @strict_loading end
Возвращает true, если запись находится в режиме strict_loading.
# File activerecord/lib/active_record/core.rb, line 726 def strict_loading_all? @strict_loading_mode == :all end
Возвращает true, если запись использует strict_loading с включенным режимом :all.
# File activerecord/lib/active_record/core.rb, line 721 def strict_loading_n_plus_one_only? @strict_loading_mode == :n_plus_one_only end
Возвращает true, если запись использует strict_loading с включенным режимом :n_plus_one_only.
# File activerecord/lib/active_record/core.rb, line 598
Возвращает массив значений, возвращаемых указанными методами.
topic = Topic.new(title: "Budget", author_name: "Jason") topic.values_at(:title, :author_name) => ["Budget", "Jason"]
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.