module ActiveRecord::ModelSchema::ClassMethods
Открытые методы экземпляра
# File activerecord/lib/active_record/model_schema.rb, line 488 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 479
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 494 def column_names @column_names ||= columns.map(&:name).freeze end
Возвращает массив имен столбцов в виде строк.
# File activerecord/lib/active_record/model_schema.rb, line 448 def columns @columns ||= columns_hash.values.freeze end
# File activerecord/lib/active_record/model_schema.rb, line 505
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 334 def ignored_columns @ignored_columns || superclass.ignored_columns end
Список имен столбцов, которые модель должна игнорировать. Для игнорируемых столбцов не будут определены методы доступа к атрибутам, и они не будут упоминаться в SQL-запросах.
# File activerecord/lib/active_record/model_schema.rb, line 375 def ignored_columns=(columns) check_model_columns(@only_columns.present?) 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 550
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 427
def next_sequence_value
with_connection { |c| c.next_sequence_value(sequence_name) }
end Возвращает следующее значение, которое будет использовано в качестве первичного ключа в операторе вставки.
# File activerecord/lib/active_record/model_schema.rb, line 340 def only_columns @only_columns || superclass.only_columns end
Список имен столбцов, которые модели разрешено использовать. Только эти столбцы используются для определения методов доступа к атрибутам и упоминаются в SQL-запросах.
# File activerecord/lib/active_record/model_schema.rb, line 381 def only_columns=(columns) check_model_columns(@ignored_columns.present?) reload_schema_from_cache @only_columns = columns.map(&:to_s).freeze end
# File activerecord/lib/active_record/model_schema.rb, line 421
def prefetch_primary_key?
with_connection { |c| c.prefetch_primary_key?(table_name) }
end Определяет, следует ли получать значения первичного ключа из соответствующей последовательности до выполнения оператора вставки.
# File activerecord/lib/active_record/model_schema.rb, line 315
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 324 def protected_environments=(environments) @protected_environments = environments.map(&:to_s) end
Задает массив имен сред, в которых запрещены деструктивные действия.
# File activerecord/lib/active_record/model_schema.rb, line 288 def quoted_table_name adapter_class.quote_table_name(table_name) end
Возвращает имя таблицы в кавычках.
# File activerecord/lib/active_record/model_schema.rb, line 539 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.1]
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 387
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 414 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 432 def table_exists? schema_cache.data_source_exists?(table_name) end
Указывает, существует ли таблица, связанная с этим классом.
# File activerecord/lib/active_record/model_schema.rb, line 263 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, оно также будет использоваться для имени таблицы:
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 273
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 565 def initialize_load_schema_monitor @load_schema_monitor = Monitor.new end
# File activerecord/lib/active_record/model_schema.rb, line 569
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.