модуль ActiveRecord::ModelSchema::ClassMethods
Открытые методы экземпляров
# File activerecord/lib/active_record/model_schema.rb, line 472 def column_defaults load_schema @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze end
Возвращает хеш, где ключи — имена столбцов, а значения — значения по умолчанию при создании объекта Active Record для этой таблицы.
# File activerecord/lib/active_record/model_schema.rb, line 463
def column_for_attribute(name)
name = name.to_s
columns_hash.fetch(name) do
ConnectionAdapters::NullColumn.new(name)
end
end Возвращает объект столбца для заданного атрибута. Возвращает ActiveRecord::ConnectionAdapters::NullColumn, если атрибут с указанным именем не существует.
class Person < ActiveRecord::Base end person = Person.new person.column_for_attribute(:name) # the result depends on the ConnectionAdapter # => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...> person.column_for_attribute(:nothing) # => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
# File activerecord/lib/active_record/model_schema.rb, line 478 def column_names @column_names ||= columns.map(&:name).freeze end
Возвращает массив имён столбцов в виде строк.
# File activerecord/lib/active_record/model_schema.rb, line 432 def columns @columns ||= columns_hash.values.freeze end
# File activerecord/lib/active_record/model_schema.rb, line 489
def content_columns
@content_columns ||= columns.reject do |c|
c.name == primary_key ||
c.name == inheritance_column ||
c.name.end_with?("_id", "_count")
end.freeze
end Возвращает массив объектов столбцов, из которого удалены первичный идентификатор, все столбцы, оканчивающиеся на «_id» или «_count», а также столбцы, используемые для наследования по одной таблице.
# File activerecord/lib/active_record/model_schema.rb, line 331 def ignored_columns @ignored_columns || superclass.ignored_columns end
Список имён столбцов, которые модель должна игнорировать. Для игнорируемых столбцов не будут определены аксессоры атрибутов, и они не будут использоваться в запросах SQL.
# File activerecord/lib/active_record/model_schema.rb, line 366 def ignored_columns=(columns) reload_schema_from_cache @ignored_columns = columns.map(&:to_s).freeze end
Устанавливает имена столбцов, которые модель должна игнорировать. Для игнорируемых столбцов не будут определены аксессоры атрибутов, и они не будут использоваться в запросах SQL.
Часто используется для того, чтобы убедиться, что все ссылки на атрибут удалены, прежде чем миграция для удаления столбца из базы данных будет применена. Такой двухступенчатый подход гарантирует отсутствие ошибок из-за кэшированной схемы в памяти во время выполнения миграции схемы.
Например, для удаления атрибута «category» сначала отметьте его как игнорируемый:
class Project < ActiveRecord::Base # schema: # id :bigint # name :string, limit: 255 # category :string, limit: 255 self.ignored_columns += [:category] end
Схема все еще содержит «category», но теперь модель его пропускает, поэтому любой код или кэширование схемы на основе метаданных не будут пытаться использовать столбец:
Project.columns_hash["category"] => nil
При прямом обращении к этому атрибуту произойдет ошибка, поэтому убедитесь, что все использования столбца удалены (автоматические тесты помогут вам найти все его использования).
user = Project.create!(name: "First Project") user.category # => raises NoMethodError
# File activerecord/lib/active_record/model_schema.rb, line 534
def load_schema
return if schema_loaded?
@load_schema_monitor.synchronize do
return if schema_loaded?
load_schema!
@schema_loaded = true
rescue
reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
raise
end
end Загружает информацию о схеме модели либо из кэша схемы, либо непосредственно из базы данных.
# File activerecord/lib/active_record/model_schema.rb, line 411
def next_sequence_value
with_connection { |c| c.next_sequence_value(sequence_name) }
end Возвращает следующее значение, которое будет использоваться в качестве первичного ключа в операторе вставки.
# File activerecord/lib/active_record/model_schema.rb, line 405
def prefetch_primary_key?
with_connection { |c| c.prefetch_primary_key?(table_name) }
end Определяет, должны ли значения первичного ключа выбираться из соответствующей последовательности перед оператором вставки.
# File activerecord/lib/active_record/model_schema.rb, line 312
def protected_environments
if defined?(@protected_environments)
@protected_environments
else
superclass.protected_environments
end
end Массив имён сред, в которых запрещены деструктивные действия. По умолчанию значение равно ["production"].
# File activerecord/lib/active_record/model_schema.rb, line 321 def protected_environments=(environments) @protected_environments = environments.map(&:to_s) end
Устанавливает массив имён сред, в которых запрещены деструктивные действия.
# File activerecord/lib/active_record/model_schema.rb, line 285 def quoted_table_name adapter_class.quote_table_name(table_name) end
Возвращает цитированную версию имени таблицы.
# File activerecord/lib/active_record/model_schema.rb, line 523 def reset_column_information connection_pool.active_connection&.clear_cache! ([self] + descendants).each(&:undefine_attribute_methods) schema_cache.clear_data_source_cache!(table_name) reload_schema_from_cache initialize_find_by_cache end
Сбрасывает всю кэшированную информацию о столбцах, что приведет к их перезагрузке при следующем запросе.
Наиболее распространённое использование этого метода, вероятно, в миграции, когда сразу после создания таблицы вы хотите заполнить её некоторыми значениями по умолчанию, например:
class CreateJobLevels < ActiveRecord::Migration[8.0]
def up
create_table :job_levels do |t|
t.integer :id
t.string :name
t.timestamps
end
JobLevel.reset_column_information
%w{assistant executive manager director}.each do |type|
JobLevel.create(name: type)
end
end
def down
drop_table :job_levels
end
end
# File activerecord/lib/active_record/model_schema.rb, line 371
def sequence_name
if base_class?
@sequence_name ||= reset_sequence_name
else
(@sequence_name ||= nil) || base_class.sequence_name
end
end # File activerecord/lib/active_record/model_schema.rb, line 398 def sequence_name=(value) @sequence_name = value.to_s @explicit_sequence_name = true end
Устанавливает имя последовательности для генерации идентификаторов заданному значению, или (если значение равно nil или false) значению, возвращаемому заданным блоком. Это необходимо для Oracle и полезно для любой базы данных, которая использует последовательности для генерации первичных ключей.
Если имя последовательности не установлено явно при использовании Oracle, оно будет по умолчанию равно: #{table_name}_seq
Если имя последовательности не установлено явно при использовании PostgreSQL, оно будет обнаружено для вашего первичного ключа.
class Project < ActiveRecord::Base self.sequence_name = "projectseq" # default would have been "project_seq" end
# File activerecord/lib/active_record/model_schema.rb, line 416 def table_exists? schema_cache.data_source_exists?(table_name) end
Указывает, существует ли таблица, связанная с этим классом.
# File activerecord/lib/active_record/model_schema.rb, line 260 def table_name reset_table_name unless defined?(@table_name) @table_name end
Определяет имя таблицы (в принудительно нижнем регистре) на основе имени класса в иерархии наследования, непосредственно унаследованной от ActiveRecord::Base. Таким образом, если иерархия выглядит как: Reply < Message < ActiveRecord::Base, то Message используется для определения имени таблицы даже при вызове из Reply. Правила определения имени таблицы обрабатываются классом Inflector в Active Support, который знает практически все распространённые английские склонения. Вы можете добавить новые склонения в файл config/initializers/inflections.rb.
Вложенным классам присваиваются имена таблиц, начинающиеся с единственного числа имени родительской таблицы. Вложенные модули не рассматриваются.
Примеры
class Invoice < ActiveRecord::Base end file class table_name invoice.rb Invoice invoices class Invoice < ActiveRecord::Base class Lineitem < ActiveRecord::Base end end file class table_name invoice.rb Invoice::Lineitem invoice_lineitems module Invoice class Lineitem < ActiveRecord::Base end end file class table_name invoice/lineitem.rb Invoice::Lineitem lineitems
Кроме того, к имени класса добавляется префикс уровня класса table_name_prefix и суффикс table_name_suffix. Таким образом, если у вас есть префикс «myapp_», то предполагаемое имя таблицы для класса Invoice становится «myapp_invoices». Invoice::Lineitem станет «myapp_invoice_lineitems».
Базовое имя, используемое для определения имени таблицы, — это model_name из Active Model Naming. В случае определения пользовательского имени Active Model Name, оно также будет использоваться для имени таблицы:
class PostRecord < ActiveRecord::Base
class << self
def model_name
ActiveModel::Name.new(self, nil, "Post")
end
end
end
PostRecord.table_name
# => "posts"
Также вы можете явно задать имя таблицы:
class Mouse < ActiveRecord::Base self.table_name = "mice" end
# File activerecord/lib/active_record/model_schema.rb, line 270
def table_name=(value)
value = value && value.to_s
if defined?(@table_name)
return if value == @table_name
reset_column_information if connected?
end
@table_name = value
@arel_table = nil
@sequence_name = nil unless @explicit_sequence_name
@predicate_builder = nil
end Явно устанавливает имя таблицы. Пример:
class Project < ActiveRecord::Base self.table_name = "project" end
Защищённые методы экземпляра
# File activerecord/lib/active_record/model_schema.rb, line 549 def initialize_load_schema_monitor @load_schema_monitor = Monitor.new end
# File activerecord/lib/active_record/model_schema.rb, line 553
def reload_schema_from_cache(recursive = true)
@_returning_columns_for_insert = nil
@arel_table = nil
@column_names = nil
@symbol_column_to_string_name_hash = nil
@content_columns = nil
@column_defaults = nil
@attributes_builder = nil
@columns = nil
@columns_hash = nil
@schema_loaded = false
@attribute_names = nil
@yaml_encoder = nil
if recursive
subclasses.each do |descendant|
descendant.send(:reload_schema_from_cache)
end
end
end
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.