module PgSaurus::ConnectionAdapters::PostgreSQLAdapter::ForeignKeyMethods

Provides methods to extend {ActiveRecord::ConnectionAdapters::PostgreSQLAdapter} to support foreign keys feature.

Public Instance Methods

add_foreign_key(from_table, to_table, options = {}) click to toggle source

See activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb

Creates index on the FK column by default. Pass in the option exclude_index: true to disable this.

Calls superclass method
# File lib/pg_saurus/connection_adapters/postgresql_adapter/foreign_key_methods.rb, line 27
def add_foreign_key(from_table, to_table, options = {})
  exclude_index = (options.has_key?(:exclude_index) ? options.delete(:exclude_index) : false)
  column        = options[:column] || foreign_key_column_for(to_table)

  if index_exists?(from_table, column) && !exclude_index
    raise PgSaurus::IndexExistsError,
          "The index, #{index_name(from_table, column)}, already exists." \
      "  Use :exclude_index => true when adding the foreign key."
  end

  super from_table, to_table, **options

  unless exclude_index
    add_index from_table, column
  end
end
drop_table(*args) click to toggle source

Drop table and optionally disable triggers. Changes adapted from github.com/matthuhiggins/foreigner/blob/e72ab9c454c156056d3f037d55e3359cd972af32/lib/foreigner/connection_adapters/sql2003.rb NOTE: Disabling referential integrity requires superuser access in postgres.

Default AR behavior is just to drop_table.

Options:

  • :force - force disabling of referential integrity

Note: I don’t know a good way to test this -mike 20120420

Calls superclass method
# File lib/pg_saurus/connection_adapters/postgresql_adapter/foreign_key_methods.rb, line 14
def drop_table(*args)
  options = args.clone.extract_options!
  if options[:force]
    disable_referential_integrity { super }
  else
    super
  end
end
foreign_key_column_for(table_name) click to toggle source

See: activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb

Removes schema name from table name.

Calls superclass method
# File lib/pg_saurus/connection_adapters/postgresql_adapter/foreign_key_methods.rb, line 60
def foreign_key_column_for(table_name)
  table = table_name.to_s.split('.').last

  super table
end
foreign_keys(table_name) click to toggle source

See activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb

Add from_schema option to foreign key definition options.

# File lib/pg_saurus/connection_adapters/postgresql_adapter/foreign_key_methods.rb, line 69
    def foreign_keys(table_name)
      namespace  = table_name.to_s.split('.').first
      table_name = table_name.to_s.split('.').last

      namespace  = if namespace == table_name
                     "ANY (current_schemas(false))"
                   else
                     quote(namespace)
                   end

      sql = <<-SQL.strip_heredoc
            SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, t3.nspname AS from_schema
            FROM pg_constraint c
            JOIN pg_class t1 ON c.conrelid = t1.oid
            JOIN pg_class t2 ON c.confrelid = t2.oid
            JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
            JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
            JOIN pg_namespace t3 ON c.connamespace = t3.oid
            WHERE c.contype = 'f'
              AND t1.relname = #{quote(table_name)}
              AND t3.nspname = #{namespace}
            ORDER BY c.conname
      SQL

      fk_info = select_all(sql)

      fk_info.map do |row|
        options = {
          column:      row['column'],
          name:        row['name'],
          primary_key: row['primary_key'],
          from_schema: row['from_schema']
        }

        options[:on_delete] = extract_foreign_key_action(row['on_delete'])
        options[:on_update] = extract_foreign_key_action(row['on_update'])

        ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(table_name, row['to_table'], options)
      end
    end
remove_foreign_key(from_table, to_table = nil, **options) click to toggle source

See activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb

Pass in the option remove_index: true to remove index as well.

Calls superclass method
# File lib/pg_saurus/connection_adapters/postgresql_adapter/foreign_key_methods.rb, line 47
def remove_foreign_key(from_table, to_table = nil, **options)
  if options[:remove_index]
    column = options[:column]
    remove_index from_table, column
    options.delete(:remove_index)
  end

  super(from_table, to_table, **options)
end