Module: SchemaPlus::ForeignKeys::ActiveRecord::ConnectionAdapters::AbstractAdapter

Defined in:
lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb

Overview

SchemaPlus::ForeignKeys adds several methods to ActiveRecord::ConnectionAdapters::AbstractAdapter. In most cases you don't call these directly, but rather the methods that define things are called by schema statements, and methods that query things are called by ActiveRecord::Base.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.proper_table_name(name) ⇒ Object



55
56
57
# File 'lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb', line 55

def self.proper_table_name(name)
  proper_name = ::ActiveRecord::Migration.new.proper_table_name(name)
end

Instance Method Details

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

:nodoc:



51
52
53
# File 'lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb', line 51

def _build_foreign_key(from_table, to_table, options = {}) #:nodoc:
  ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(from_table, AbstractAdapter.proper_table_name(to_table), options)
end

#add_foreign_key(*args) ⇒ Object

Define a foreign key constraint. Valid options are :on_update, :on_delete, and :deferrable, with values as described at ConnectionAdapters::ForeignKeyDefinition

(NOTE: Sqlite3 does not support altering a table to add foreign-key constraints; they must be included in the table specification when it's created. If you're using Sqlite3, this method will raise an error.)



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb', line 25

def add_foreign_key(*args) # (table_name, column, to_table, primary_key, options = {})
  options = args.extract_options!
  case args.length
  when 2
    from_table, to_table = args
  when 4
    ActiveSupport::Deprecation.warn "4-argument form of add_foreign_key is deprecated.  use add_foreign_key(from_table, to_table, options)"
    (from_table, column, to_table, primary_key) = args
    options.merge!(column: column, primary_key: primary_key)
  end

  options = options.dup
  options[:column] ||= foreign_key_column_for(to_table)
  options[:name]   ||= ForeignKeyDefinition.default_name(from_table, options[:column])

  foreign_key_sql = add_foreign_key_sql(from_table, to_table, options)
  execute "ALTER TABLE #{quote_table_name(from_table)} #{foreign_key_sql}"
end

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

called directly by AT's bulk_change_table, for migration change_table :name, :bulk => true { … }



46
47
48
49
# File 'lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb', line 46

def add_foreign_key_sql(from_table, to_table, options = {}) #:nodoc:
  foreign_key = ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(from_table, AbstractAdapter.proper_table_name(to_table), options)
  "ADD #{foreign_key.to_sql}"
end

#foreign_keys(table_name, name = nil) ⇒ Object

(abstract) Return the ForeignKeyDefinition objects for foreign key constraints defined on this table



139
# File 'lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb', line 139

def foreign_keys(table_name, name = nil) raise "Internal Error: Connection adapter didn't override abstract function"; [] end

#get_foreign_key_name(from_table, to_table, options) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb', line 107

def get_foreign_key_name(from_table, to_table, options)
  return options[:name] if options[:name]

  fks = foreign_keys(from_table)
  if fks.detect(&its.name == to_table)
    ActiveSupport::Deprecation.warn "remove_foreign_key(table, name) is deprecated.  use remove_foreign_key(table, name: name)"
    return to_table
  end
  test_fk = _build_foreign_key(from_table, to_table, options)
  if fk = fks.detect { |fk| fk.match(test_fk) }
    fk.name
  else
    raise "SchemaPlus::ForeignKeys: no foreign key constraint found on #{from_table.inspect} matching #{[to_table, options].inspect}" unless options[:if_exists]
    nil
  end
end

#normalize_remove_foreign_key_args(*args) ⇒ Object



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
# File 'lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb', line 77

def normalize_remove_foreign_key_args(*args)
  options = args.extract_options!
  if options.has_key? :column_names
    ActiveSupport::Deprecation.warn ":column_names option is deprecated, use :column"
    options[:column] = options.delete(:column_names)
  end
  if options.has_key? :references_column_names
    ActiveSupport::Deprecation.warn ":references_column_names option is deprecated, use :primary_key"
    options[:primary_key] = options.delete(:references_column_names)
  end
  if options.has_key? :references_table_name
    ActiveSupport::Deprecation.warn ":references_table_name option is deprecated, use :to_table"
    options[:to_table] = options.delete(:references_table_name)
  end
  case args.length
  when 1
    from_table = args[0]
  when 2
    from_table, to_table = args
  when 3, 4
    ActiveSupport::Deprecation.warn "3- and 4-argument forms of remove_foreign_key are deprecated.  use add_foreign_key(from_table, to_table, options)"
    (from_table, column, to_table, primary_key) = args
    options.merge!(column: column, primary_key: primary_key)
  else
    raise ArgumentError, "Wrong number of arguments(#{args.length}) to remove_foreign_key"
  end
  to_table ||= options.delete(:to_table)
  [from_table, to_table, options]
end

#remove_foreign_key(*args) ⇒ Object

Remove a foreign key constraint

Arguments are the same as for add_foreign_key, or by name:

remove_foreign_key table_name, to_table, options
remove_foreign_key table_name, name: constraint_name

(NOTE: Sqlite3 does not support altering a table to remove foreign-key constraints. If you're using Sqlite3, this method will raise an error.)



69
70
71
72
73
74
75
# File 'lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb', line 69

def remove_foreign_key(*args)
  from_table, to_table, options = normalize_remove_foreign_key_args(*args)
  options[:column] ||= foreign_key_column_for(to_table)
  if sql = remove_foreign_key_sql(from_table, to_table, options)
    execute "ALTER TABLE #{quote_table_name(from_table)} #{sql}"
  end
end

#remove_foreign_key_sql(from_table, to_table, options) ⇒ Object



124
125
126
127
128
# File 'lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb', line 124

def remove_foreign_key_sql(from_table, to_table, options)
  if foreign_key_name = get_foreign_key_name(from_table, to_table, options)
    "DROP CONSTRAINT #{options[:if_exists] ? "IF EXISTS" : ""} #{foreign_key_name}"
  end
end

#reverse_foreign_keys(table_name, name = nil) ⇒ Object

(abstract) Return the ForeignKeyDefinition objects for foreign key constraints defined on other tables that reference this table



143
# File 'lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb', line 143

def reverse_foreign_keys(table_name, name = nil) raise "Internal Error: Connection adapter didn't override abstract function"; [] end