123456789_123456789_123456789_123456789_123456789_

Class: ActiveRecord::InternalMetadata

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

Overview

This class is used to create a table that keeps track of values and keys such as which environment migrations were run in.

This is enabled by default. To disable this functionality set use_metadata_table to false in your database configuration.

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(pool) ⇒ InternalMetadata

[ GitHub ]

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

def initialize(pool)
  @pool = pool
  @arel_table = Arel::Table.new(table_name)
end

Instance Attribute Details

#arel_table (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 16

attr_reader :arel_table

#enabled?Boolean (readonly)

[ GitHub ]

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

def enabled?
  @pool.db_config.
end

#table_exists?Boolean (readonly)

[ GitHub ]

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

def table_exists?
  @pool.schema_cache.data_source_exists?(table_name)
end

Instance Method Details

#[](key)

[ GitHub ]

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

def [](key)
  return unless enabled?

  @pool.with_connection do |connection|
    if entry = select_entry(connection, key)
      entry[value_key]
    end
  end
end

#[]=(key, value)

[ GitHub ]

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

def []=(key, value)
  return unless enabled?

  @pool.with_connection do |connection|
    update_or_create_entry(connection, key, value)
  end
end

#count

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 65

def count
  sm = Arel::SelectManager.new(arel_table)
  sm.project(*Arel::Nodes::Count.new([Arel.star]))

  @pool.with_connection do |connection|
    connection.select_values(sm, "#{self.class} Count").first
  end
end

#create_entry(connection, key, value) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 130

def create_entry(connection, key, value)
  im = Arel::InsertManager.new(arel_table)
  im.insert [
    [arel_table[primary_key], key],
    [arel_table[value_key], value],
    [arel_table[:created_at], current_time(connection)],
    [arel_table[:updated_at], current_time(connection)]
  ]

  connection.insert(im, "#{self.class} Create", primary_key, key)
end

#create_table

Creates an internal metadata table with columns key and value

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 85

def create_table
  return unless enabled?

  @pool.with_connection do |connection|
    unless connection.table_exists?(table_name)
      connection.create_table(table_name, id: false) do |t|
        t.string :key, **connection.internal_string_options_for_primary_key
        t.string :value
        t.timestamps
      end
    end
  end
end

#create_table_and_set_flags(environment, schema_sha1 = nil)

[ GitHub ]

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

def create_table_and_set_flags(environment, schema_sha1 = nil)
  return unless enabled?

  @pool.with_connection do |connection|
    create_table
    update_or_create_entry(connection, :environment, environment)
    update_or_create_entry(connection, :schema_sha1, schema_sha1) if schema_sha1
  end
end

#current_time(connection) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 126

def current_time(connection)
  connection.default_timezone == :utc ? Time.now.utc : Time.now
end

#delete_all_entries

[ GitHub ]

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

def delete_all_entries
  dm = Arel::DeleteManager.new(arel_table)

  @pool.with_connection do |connection|
    connection.delete(dm, "#{self.class} Destroy")
  end
end

#drop_table

[ GitHub ]

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

def drop_table
  return unless enabled?

  @pool.with_connection do |connection|
    connection.drop_table table_name, if_exists: true
  end
end

#primary_key

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 23

def primary_key
  "key"
end

#select_entry(connection, key) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 154

def select_entry(connection, key)
  sm = Arel::SelectManager.new(arel_table)
  sm.project(Arel::Nodes::SqlLiteral.new("*", retryable: true))
  sm.where(arel_table[primary_key].eq(Arel::Nodes::BindParam.new(key)))
  sm.order(arel_table[primary_key].asc)
  sm.limit = 1

  connection.select_all(sm, "#{self.class} Load").first
end

#table_name

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 31

def table_name
  "#{ActiveRecord::Base.table_name_prefix}#{ActiveRecord::Base.}#{ActiveRecord::Base.table_name_suffix}"
end

#update_entry(connection, key, new_value) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 142

def update_entry(connection, key, new_value)
  um = Arel::UpdateManager.new(arel_table)
  um.set [
    [arel_table[value_key], new_value],
    [arel_table[:updated_at], current_time(connection)]
  ]

  um.where(arel_table[primary_key].eq(key))

  connection.update(um, "#{self.class} Update")
end

#update_or_create_entry(connection, key, value) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 112

def update_or_create_entry(connection, key, value)
  entry = select_entry(connection, key)

  if entry
    if entry[value_key] != value
      update_entry(connection, key, value)
    else
      entry[value_key]
    end
  else
    create_entry(connection, key, value)
  end
end

#value_key

[ GitHub ]

  
# File 'activerecord/lib/active_record/internal_metadata.rb', line 27

def value_key
  "value"
end