module Torque::PostgreSQL::SchemaCache

:todo: Create the add to load inheritance info

Public Instance Methods

add_model_name(table_name, model) click to toggle source

A way to manually add models name so it doesn't need the lookup method

# File lib/torque/postgresql/schema_cache.rb, line 92
def add_model_name(table_name, model)
  return unless data_source_exists?(table_name) && model.is_a?(Class)
  @data_sources_model_names[table_name] = model
end
associations(table_name) click to toggle source

Get the list of all tables that are associated (direct or indirect inheritance) with the provided one

# File lib/torque/postgresql/schema_cache.rb, line 105
def associations(table_name)
  reload_inheritance_data!
  @inheritance_associations[table_name]
end
dependencies(table_name) click to toggle source

Get all the tables that the given one inherits from

# File lib/torque/postgresql/schema_cache.rb, line 98
def dependencies(table_name)
  reload_inheritance_data!
  @inheritance_dependencies[table_name]
end
lookup_model(table_name, scoped_class = '') click to toggle source

Try to find a model based on a given table

# File lib/torque/postgresql/schema_cache.rb, line 111
      def lookup_model(table_name, scoped_class = '')
        scoped_class = scoped_class.name if scoped_class.is_a?(Class)
        return @data_sources_model_names[table_name] \
          if @data_sources_model_names.key?(table_name)

        # Get all the possible scopes
        scopes = scoped_class.scan(/(?:::)?[A-Z][a-z]+/)
        scopes.unshift('Object::')

        # Consider the maximum namespaced possible model name
        max_name = table_name.tr('_', '/').camelize.split(/(::)/)
        max_name[-1] = max_name[-1].singularize

        # Test all the possible names against all the possible scopes
        until scopes.size == 0
          scope = scopes.join.safe_constantize
          model = find_model(max_name, table_name, scope) unless scope.nil?
          return @data_sources_model_names[table_name] = model unless model.nil?
          scopes.pop
        end

        # If this part is reach, no model name was found
        raise LookupError.new(<<~MSG.squish)
          Unable to find a valid model that is associated with the '#{table_name}' table.
          Please, check if they correctly inherit from ActiveRecord::Base
        MSG
      end

Private Instance Methods

find_model(max_name, table_name, scope = Object) click to toggle source

Find a model by a given max namespaced class name thath matches the given table name

# File lib/torque/postgresql/schema_cache.rb, line 143
def find_model(max_name, table_name, scope = Object)
  pieces = max_name.is_a?(::Array) ? max_name : max_name.split(/(::)/)
  ns_places = (1..(max_name.size - 1)).step(2).to_a

  # Generate all possible combinarions
  conditions = []
  range = Torque::PostgreSQL.config.inheritance.inverse_lookup \
    ? 0.upto(ns_places.size) \
    : ns_places.size.downto(0)
  range.each do |size|
    conditions.concat(ns_places.combination(size).to_a)
  end

  # Now iterate over
  while (condition = conditions.shift)
    ns_places.each{ |i| pieces[i] = condition.include?(i) ? '::' : '' }

    candidate = pieces.join
    candidate.prepend("#{scope.name}::") unless scope === Object

    klass = candidate.safe_constantize
    next if klass.nil?

    # Check if the class match the table name
    return klass if klass < ::ActiveRecord::Base && klass.table_name == table_name
  end
end
generate_associations() click to toggle source

Calculates the inverted dependency (association), where even indirect inheritance comes up in the list

# File lib/torque/postgresql/schema_cache.rb, line 182
def generate_associations
  return {} if @inheritance_dependencies.empty?

  result = Hash.new{ |h, k| h[k] = [] }
  masters = @inheritance_dependencies.values.flatten.uniq

  # Add direct associations
  masters.map do |master|
    @inheritance_dependencies.each do |(dependent, associations)|
      result[master] << dependent if associations.include?(master)
    end
  end

  # Add indirect associations
  result.each do |master, children|
    children.each do |child|
      children.concat(result[child]).uniq! if result.key?(child)
    end
  end

  # Remove the default proc that would create new entries
  result.default_proc = nil
  result
end
prepare_data_sources() click to toggle source

Use this method to also load any irregular model name. This is smart enought to only load the sources present on this instance

Calls superclass method
# File lib/torque/postgresql/schema_cache.rb, line 209
def prepare_data_sources
  super
  @data_sources_model_names = Torque::PostgreSQL.config
    .irregular_models.slice(*@data_sources.keys).map do |table_name, model_name|
    [table_name, (model_name.is_a?(Class) ? model_name : model_name.constantize)]
  end.to_h
end
reload_inheritance_data!() click to toggle source

Reload information about tables inheritance and dependencies, uses a cache to not perform additional checkes

# File lib/torque/postgresql/schema_cache.rb, line 173
def reload_inheritance_data!
  return if @inheritance_loaded
  @inheritance_dependencies = connection.inherited_tables
  @inheritance_associations = generate_associations
  @inheritance_loaded = true
end