модуль ActiveRecord::Core
Методы публичного класса
# File activerecord/lib/active_record/core.rb, line 69 def self.configurations @@configurations end
Возвращает полностью разрешённый объект ActiveRecord::DatabaseConfigurations
# File activerecord/lib/active_record/core.rb, line 63 def self.configurations=(config) @@configurations = ActiveRecord::DatabaseConfigurations.new(config) end
Содержит конфигурацию базы данных — как обычно хранится в config/database.yml — в виде объекта ActiveRecord::DatabaseConfigurations.
Например, следующий database.yml…
development: adapter: sqlite3 database: db/development.sqlite3 production: adapter: sqlite3 database: db/production.sqlite3
…приведёт к тому, что ActiveRecord::Base.configurations будет выглядеть так:
#<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
#<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
@name="primary", @config={adapter: "sqlite3", database: "db/development.sqlite3"}>,
#<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
@name="primary", @config={adapter: "sqlite3", database: "db/production.sqlite3"}>
]> # File activerecord/lib/active_record/core.rb, line 160 def self.connection_handler Thread.current.thread_variable_get(:ar_connection_handler) || default_connection_handler end
# File activerecord/lib/active_record/core.rb, line 164 def self.connection_handler=(handler) Thread.current.thread_variable_set(:ar_connection_handler, handler) end
# File activerecord/lib/active_record/core.rb, line 168
def self.connection_handlers
unless legacy_connection_handling
raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
end
@@connection_handlers ||= {}
end # File activerecord/lib/active_record/core.rb, line 176
def self.connection_handlers=(handlers)
unless legacy_connection_handling
raise NotImplementedError, "The new connection handling does not setting support multiple connection handlers."
end
@@connection_handlers = handlers
end # File activerecord/lib/active_record/core.rb, line 234
def self.current_preventing_writes
if legacy_connection_handling
connection_handler.prevent_writes
else
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?(abstract_base_class)
end
false
end
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 193
def self.current_role
if ActiveRecord::Base.legacy_connection_handling
connection_handlers.key(connection_handler) || default_role
else
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?(abstract_base_class)
end
default_role
end
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 215
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?(abstract_base_class)
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 471 def initialize(attributes = nil) @new_record = true @attributes = self.class._default_attributes.deep_dup init_internals initialize_internals_callback assign_attributes(attributes) if attributes 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 622
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 590
def ==(comparison_object)
super ||
comparison_object.instance_of?(self.class) &&
!id.nil? &&
comparison_object.id == id
end Возвращает true, если comparison_object — это тот же самый объект, или comparison_object имеет тот же тип и self имеет идентификатор, равный comparison_object.id.
Обратите внимание, что новые записи по определению отличаются от любых других записей, если только другая запись не является самим получателем. Кроме того, если вы извлекаете существующие записи с помощью select и опускаете идентификатор, вы действуете на свой страх и риск; в этом случае предикат вернёт false.
Также обратите внимание, что удаление записи сохраняет её идентификатор в экземпляре модели, поэтому удалённые модели всё ещё сравнимы.
# File activerecord/lib/active_record/core.rb, line 523
Идентичен методу 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 664 def connection_handler self.class.connection_handler end
# File activerecord/lib/active_record/core.rb, line 540
Дублированные объекты не имеют назначенного идентификатора и рассматриваются как новые записи. Обратите внимание, что это «поверхностная» копия, так как она копирует только атрибуты объекта, а не его ассоциации. Степень «глубокой» копии зависит от приложения и поэтому должна быть реализована приложением в соответствии с его потребностями. Метод dup не сохраняет отметки времени (created|updated)_(at|on).
# File activerecord/lib/active_record/core.rb, line 575 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 611 def freeze @attributes = @attributes.clone.freeze self end
Клонирует и замораживает хэш атрибутов, так что ассоциации по-прежнему доступны, даже для удаленных записей, но клонированные модели не будут заморожены.
# File activerecord/lib/active_record/core.rb, line 617 def frozen? @attributes.frozen? end
Возвращает true, если хэш атрибутов был заморожен.
# File activerecord/lib/active_record/core.rb, line 600
def hash
if id
self.class.hash ^ id.hash
else
super
end
end Делегирует идентификатору, чтобы две записи одного типа и с одним идентификатором могли работать с чем-то вроде:
[ 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 498 def init_with(coder, &block) coder = LegacyYamlAdapter.convert(self.class, 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 669
def inspect
# We check defined?(@attributes) not to issue warnings if the object is
# allocated but not initialized.
inspection = if defined?(@attributes) && @attributes
self.class.attribute_names.collect do |name|
if _has_attribute?(name)
"#{name}: #{attribute_for_inspect(name)}"
end
end.compact.join(", ")
else
"not initialized"
end
"#<#{self.class} #{inspection}>"
end Возвращает содержимое записи в виде отформатированной строки.
# File activerecord/lib/active_record/core.rb, line 687
def pretty_print(pp)
return super if custom_inspect_method_defined?
pp.object_address_group(self) do
if defined?(@attributes) && @attributes
attr_names = self.class.attribute_names.select { |name| _has_attribute?(name) }
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
pp.breakable " "
pp.group(1) do
pp.text attr_name
pp.text ":"
pp.breakable
value = _read_attribute(attr_name)
value = inspection_filter.filter_param(attr_name, value) unless value.nil?
pp.pp 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 660 def readonly! @readonly = true end
Помечает эту запись как только для чтения.
# File activerecord/lib/active_record/core.rb, line 639 def readonly? @readonly end
Возвращает true, если запись только для чтения.
# File activerecord/lib/active_record/core.rb, line 711
def slice(*methods)
methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
end Возвращает хэш заданных методов с их именами в качестве ключей и возвращаемыми значениями в качестве значений.
# File activerecord/lib/active_record/core.rb, line 655 def strict_loading! @strict_loading = true end
Устанавливает режим strict_loading для записи. Это вызовет ошибку, если запись попытается загрузить ассоциацию лениво.
user = User.first user.strict_loading! user.comments.to_a => ActiveRecord::StrictLoadingViolationError
# File activerecord/lib/active_record/core.rb, line 644 def strict_loading? @strict_loading end
Возвращает true, если запись находится в режиме strict_loading.
# File activerecord/lib/active_record/core.rb, line 716
def values_at(*methods)
methods.flatten.map! { |method| public_send(method) }
end Возвращает массив значений, возвращаемых заданными методами.
© 2004–2020 David Heinemeier Hansson
Licensed under the MIT License.