Spec-Zone.ru › Ruby on Rails 8.1

module ActiveRecord::ModelSchema::ClassMethods

Открытые методы экземпляра

column_defaults () Показать исходный код
# 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 для этой таблицы.

column_for_attribute (name) Показать исходный код
# 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>, ...>
column_names () Показать исходный код
# File activerecord/lib/active_record/model_schema.rb, line 494
def column_names
  @column_names ||= columns.map(&:name).freeze
end

Возвращает массив имен столбцов в виде строк.

columns () Показать исходный код
# File activerecord/lib/active_record/model_schema.rb, line 448
def columns
  @columns ||= columns_hash.values.freeze
end
content_columns () Показать исходный код
# 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», а также столбцы, используемые для наследования с одной таблицей.

ignored_columns () Показать исходный код
# File activerecord/lib/active_record/model_schema.rb, line 334
def ignored_columns
  @ignored_columns || superclass.ignored_columns
end

Список имен столбцов, которые модель должна игнорировать. Для игнорируемых столбцов не будут определены методы доступа к атрибутам, и они не будут упоминаться в SQL-запросах.

ignored_columns= (columns) Показать исходный код
# 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
load_schema () Показать исходный код
# 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

Загружает сведения о схеме модели из кэша схемы или непосредственно из базы данных.

next_sequence_value () Показать исходный код
# File activerecord/lib/active_record/model_schema.rb, line 427
def next_sequence_value
  with_connection { |c| c.next_sequence_value(sequence_name) }
end

Возвращает следующее значение, которое будет использовано в качестве первичного ключа в операторе вставки.

only_columns () Показать исходный код
# File activerecord/lib/active_record/model_schema.rb, line 340
def only_columns
  @only_columns || superclass.only_columns
end

Список имен столбцов, которые модели разрешено использовать. Только эти столбцы используются для определения методов доступа к атрибутам и упоминаются в SQL-запросах.

only_columns= (columns) Показать исходный код
# 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
prefetch_primary_key? () Показать исходный код
# File activerecord/lib/active_record/model_schema.rb, line 421
def prefetch_primary_key?
  with_connection { |c| c.prefetch_primary_key?(table_name) }
end

Определяет, следует ли получать значения первичного ключа из соответствующей последовательности до выполнения оператора вставки.

protected_environments () Показать исходный код
# 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"].

protected_environments= (environments) Показать исходный код
# File activerecord/lib/active_record/model_schema.rb, line 324
def protected_environments=(environments)
  @protected_environments = environments.map(&:to_s)
end

Задает массив имен сред, в которых запрещены деструктивные действия.

quoted_table_name () Показать исходный код
# File activerecord/lib/active_record/model_schema.rb, line 288
def quoted_table_name
  adapter_class.quote_table_name(table_name)
end

Возвращает имя таблицы в кавычках.

reset_column_information () Показать исходный код
# 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
sequence_name () Показать исходный код
# 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
sequence_name= (value) Показать исходный код
# 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
table_exists? () Показать исходный код
# File activerecord/lib/active_record/model_schema.rb, line 432
def table_exists?
  schema_cache.data_source_exists?(table_name)
end

Указывает, существует ли таблица, связанная с этим классом.

table_name () Показать исходный код
# 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
table_name= (value) Показать исходный код
# 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

Защищенные методы экземпляра

initialize_load_schema_monitor () Показать исходный код
# File activerecord/lib/active_record/model_schema.rb, line 565
def initialize_load_schema_monitor
  @load_schema_monitor = Monitor.new
end
reload_schema_from_cache (recursive = true) Показать исходный код
# 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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API