123456789_123456789_123456789_123456789_123456789_

Class: ActiveRecord::ModelSchema::SchemaContext

Do not use. This class is for internal use only.
Relationships & Source Files
Inherits: Object
Defined in: activerecord/lib/active_record/model_schema/schema_context.rb

Overview

SchemaContext owns all schema-derived state for a model: columns, attribute types, and column defaults.

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(model_class) ⇒ SchemaContext

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 13

def initialize(model_class)
  @model_class = model_class
  @schema_loaded = false
end

Instance Attribute Details

#attribute_types (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 10

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :attribute_types, :content_columns

#column_names (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 10

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :attribute_types, :content_columns

#columns (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 10

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :attribute_types, :content_columns

#columns_hash (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 10

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :attribute_types, :content_columns

#content_columns (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 10

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :attribute_types, :content_columns

#model_class (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 10

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :attribute_types, :content_columns

#schema_loaded?Boolean (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 70

def schema_loaded?
  @schema_loaded
end

Instance Method Details

#_default_attributes

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 26

def _default_attributes
  @default_attributes
end

#_returning_columns_for_insert(connection)

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 39

def _returning_columns_for_insert(connection)
  @_returning_columns_for_insert || ActiveSupport::Ractors.on_main(self) do
    @_returning_columns_for_insert ||= begin
      auto_populated_columns = columns.filter_map do |c|
        -c.name if connection.return_value_after_insert?(c)
      end

      (auto_populated_columns.empty? ? Array(primary_key) : auto_populated_columns).freeze
    end
  end
end

#_returning_columns_for_update(connection)

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 51

def _returning_columns_for_update(connection)
  @_returning_columns_for_update ||= columns.filter_map do |c|
    c.name if connection.return_value_after_update?(c)
  end
end

#attributes_builder

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 30

def attributes_builder
  defaults = _default_attributes.except(*(column_names - Array(primary_key)))
  ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
end

#cached_find_by_statement(connection, key, &block)

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 57

def cached_find_by_statement(connection, key, &block) # :nodoc:
  cache = find_by_statement_cache[connection.prepared_statements]
  cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
end

#column_defaults

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 35

def column_defaults
  @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
end

#find_by_statement_cache

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 66

def find_by_statement_cache # :nodoc:
  ActiveSupport::Ractors[model_class.find_by_statement_cache_key] || initialize_find_by_cache
end

#initialize_find_by_cache

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 62

def initialize_find_by_cache # :nodoc:
  ActiveSupport::Ractors[model_class.find_by_statement_cache_key] = { true => Concurrent::Map.new, false => Concurrent::Map.new }
end

#load_schema!

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 74

def load_schema!
  return if @schema_loaded

  unless table_name
    raise ActiveRecord::TableNotSpecified, "#{model_class} has no table configured. Set one with #{model_class}.table_name="
  end

  columns_hash = model_class.connection_pool.schema_cache.columns_hash(table_name)
  if model_class.only_columns.present?
    columns_hash = columns_hash.slice(*model_class.only_columns)
  elsif model_class.ignored_columns.present?
    columns_hash = columns_hash.except(*model_class.ignored_columns)
  end
  @columns_hash = columns_hash.freeze

  @columns = @columns_hash.values.freeze
  @column_names = @columns.map(&:name).freeze

  @default_attributes = begin
    attributes_hash = @columns_hash.transform_values do |column|
      ActiveModel::Attribute.from_database(column.name, column.default, model_class.type_for_column(column))
    end

    attribute_set = ActiveModel::AttributeSet.new(attributes_hash)
    model_class.apply_pending_attribute_modifications(attribute_set)
    attribute_set
  end

  @attribute_types = @default_attributes.cast_types.tap do |hash|
    hash.default = ActiveModel::Type.default_value
  end

  @content_columns = @columns.reject do |c|
    Array(primary_key).include?(c.name) ||
    c.name == model_class.inheritance_column ||
    c.name.end_with?("_id", "_count")
  end.freeze

  @schema_loaded = true
end

#primary_key

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 22

def primary_key
  model_class.primary_key
end

#table_name

[ GitHub ]

  
# File 'activerecord/lib/active_record/model_schema/schema_context.rb', line 18

def table_name
  model_class.table_name
end