123456789_123456789_123456789_123456789_123456789_

Class: ActiveRecord::ModelSchema::SchemaContext

Do not use. This class is for internal use only.
Relationships & Source Files
Namespace Children
Classes:
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, column defaults, and query constraints.

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 55

def initialize(model_class)
  @model_class = model_class
  @attributes = nil
  @schema_loaded = false
  @attributes_key = :"active_record_schema_attributes_#{object_id}"
end

Instance Attribute Details

#all_timestamp_attributes_in_model (readonly)

[ GitHub ]

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

attr_reader :timestamp_attributes_for_create_in_model,
  :timestamp_attributes_for_update_in_model,
  :all_timestamp_attributes_in_model

#column_names (readonly)

[ GitHub ]

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

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :content_columns, :query_constraints_list,
            :composite_query_constraints_list, :composite_query_constraints_definition

#columns (readonly)

[ GitHub ]

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

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :content_columns, :query_constraints_list,
            :composite_query_constraints_list, :composite_query_constraints_definition

#columns_hash (readonly)

[ GitHub ]

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

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :content_columns, :query_constraints_list,
            :composite_query_constraints_list, :composite_query_constraints_definition

#composite_query_constraints_definition (readonly)

[ GitHub ]

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

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :content_columns, :query_constraints_list,
            :composite_query_constraints_list, :composite_query_constraints_definition

#composite_query_constraints_list (readonly)

[ GitHub ]

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

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :content_columns, :query_constraints_list,
            :composite_query_constraints_list, :composite_query_constraints_definition

#content_columns (readonly)

[ GitHub ]

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

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :content_columns, :query_constraints_list,
            :composite_query_constraints_list, :composite_query_constraints_definition

#has_query_constraints? ⇒ Boolean (readonly)

[ GitHub ]

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

def has_query_constraints?
  !!query_constraints
end

#model_class (readonly)

[ GitHub ]

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

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :content_columns, :query_constraints_list,
            :composite_query_constraints_list, :composite_query_constraints_definition

#query_constraints_list (readonly)

[ GitHub ]

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

attr_reader :model_class, :columns_hash, :columns, :column_names,
            :content_columns, :query_constraints_list,
            :composite_query_constraints_list, :composite_query_constraints_definition

#schema_loaded? ⇒ Boolean (readonly)

[ GitHub ]

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

def schema_loaded?
  @schema_loaded
end

#timestamp_attributes_for_create_in_model (readonly)

[ GitHub ]

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

attr_reader :timestamp_attributes_for_create_in_model,
  :timestamp_attributes_for_update_in_model,
  :all_timestamp_attributes_in_model

#timestamp_attributes_for_update_in_model (readonly)

[ GitHub ]

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

attr_reader :timestamp_attributes_for_create_in_model,
  :timestamp_attributes_for_update_in_model,
  :all_timestamp_attributes_in_model

Instance Method Details

#_returning_columns_for_insert(connection)

[ GitHub ]

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

def _returning_columns_for_insert(connection)
  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

#_returning_columns_for_update(connection)

[ GitHub ]

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

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

#attributes

[ GitHub ]

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

def attributes
  # Fast path: shareable attributes built with the schema. Otherwise
  # each Ractor builds its own.
  @attributes || (ActiveSupport::Ractors[@attributes_key] ||= Attributes.new(self, build_default_attributes))
end

#build_default_attributes

The model's columns as attributes, with its attribute declarations applied. Read only unless some default can't be frozen.

[ GitHub ]

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

def build_default_attributes # :nodoc:
  attributes = model_class.columns_hash.transform_values do |column|
    ActiveModel::Attribute.from_database(column.name, column.default, model_class.type_for_column(column))
  end
  model_class.apply_pending_attribute_modifications(attributes)

  if attributes.each_value.all?(&:freezable?)
    attributes.each_value(&:freeze)
    ActiveModel::ReadOnlyAttributeSet.new(attributes.freeze)
  else
    ActiveModel::AttributeSet.new(attributes)
  end
end

#cached_find_by_statement(connection, key, &block)

[ GitHub ]

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

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

#derive_query_constraints_list(primary_key) (private)

[ GitHub ]

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

def derive_query_constraints_list(primary_key)
  if model_class.base_class? || primary_key != model_class.base_class.primary_key
    primary_key if primary_key.is_a?(Array)
  else
    model_class.base_class.query_constraints_definition || (primary_key if primary_key.is_a?(Array))
  end
end

#find_by_statement_cache

[ GitHub ]

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

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

#freeze

[ GitHub ]

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

def freeze
  load_schema!
  super
end

#initialize_find_by_cache

[ GitHub ]

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

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 132

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

  primary_key = self.primary_key
  @query_constraints_list = query_constraints || derive_query_constraints_list(primary_key)
  @composite_query_constraints_list = (@query_constraints_list || Array(primary_key)).freeze
  @composite_query_constraints_definition = ActiveRecord::Key.for(@composite_query_constraints_list)

  @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

  @timestamp_attributes_for_create_in_model = (model_class.timestamp_attributes_for_create & @column_names).freeze
  @timestamp_attributes_for_update_in_model = (model_class.timestamp_attributes_for_update & @column_names).freeze
  @all_timestamp_attributes_in_model = (@timestamp_attributes_for_create_in_model + @timestamp_attributes_for_update_in_model).freeze

  model_class.make_pending_attribute_modifications_shareable
  default_attributes = build_default_attributes
  attributes = Attributes.new(self, default_attributes)
  if default_attributes.read_only? && ActiveSupport::Ractors.shareable?(default_attributes)
    @attributes = attributes
  else
    # Slow path: this context is made shareable after loading, and that
    # must not freeze these defaults, so only this Ractor gets them.
    ActiveSupport::Ractors[@attributes_key] = attributes
  end

  @schema_loaded = true
end

#primary_key

[ GitHub ]

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

def primary_key
  model_class.primary_key
end

#query_constraints (private)

[ GitHub ]

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

def query_constraints
  model_class.query_constraints_definition
end

#table_name

[ GitHub ]

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

def table_name
  model_class.table_name
end