Module: PgSaurus::ConnectionAdapters::PostgreSQLAdapter::ForeignKeyMethods

Included in:
PgSaurus::ConnectionAdapters::PostgreSQLAdapter
Defined in:
lib/pg_saurus/connection_adapters/postgresql_adapter/foreign_key_methods.rb

Overview

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

Instance Method Summary collapse

Instance Method Details

#add_foreign_key(from_table, to_table, options = {}) ⇒ Object

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.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 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) ⇒ Object

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



14
15
16
17
18
19
20
21
# 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) ⇒ Object

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

Removes schema name from table name.



60
61
62
63
64
# 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) ⇒ Object

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

Add from_schema option to foreign key definition options.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# 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) ⇒ Object

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

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



47
48
49
50
51
52
53
54
55
# 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