Module: SchemaPlus::ActiveRecord::ForeignKeys
- Includes:
- ColumnOptionsHandler
- Defined in:
- lib/schema_plus/active_record/foreign_keys.rb
Instance Method Summary collapse
-
#add_column(table_name, column_name, type, options = {}) ⇒ Object
Enhances ActiveRecord::ConnectionAdapters::AbstractAdapter#add_column to support indexes and foreign keys, with automatic creation.
-
#change_column(table_name, column_name, type, options = {}) ⇒ Object
Enhances ActiveRecord::Migration#change_column to support indexes and foreign keys same as add_column.
Methods included from ColumnOptionsHandler
#schema_plus_handle_column_options, #schema_plus_normalize_column_options
Instance Method Details
#add_column(table_name, column_name, type, options = {}) ⇒ Object
Enhances ActiveRecord::ConnectionAdapters::AbstractAdapter#add_column to support indexes and foreign keys, with automatic creation
Indexes
The :index
option takes a hash of parameters to pass to ActiveRecord::Migration.add_index. Thus
add_column('books', 'isbn', :string, :index => {:name => "ISBN-index", :unique => true })
is equivalent to:
add_column('books', 'isbn', :string)
add_index('books', ['isbn'], :name => "ISBN-index", :unique => true)
In order to support multi-column indexes, an special parameter :with
may be specified, which takes another column name or an array of column names to include in the index. Thus
add_column('contacts', 'phone_number', :string, :index => { :with => [:country_code, :area_code], :unique => true })
is equivalent to:
add_column('contacts', 'phone_number', :string)
add_index('contacts', ['phone_number', 'country_code', 'area_code'], :unique => true)
Some convenient shorthands are available:
add_column('books', 'isbn', :index => true) # adds index with no extra options
add_column('books', 'isbn', :index => :unique) # adds index with :unique => true
Foreign Key Constraints
The :foreign_key
option controls creation of foreign key constraints. Specifying true
or an empty hash defines a foreign key with default values. In particular, the foreign table name defaults to the column name, with trailing _id
removed, pluralized; And the foreign column name defaults to :id
add_column('widgets', 'color', :integer, :foreign_key => true)
is equivalent to
add_column('widgets', 'color_id', :integer)
add_foreign_key('widgets', 'color_id', 'colors', 'id')
As a special case, if the column is named ‘parent_id’, SchemaPlus assumes it’s a self reference, for a record that acts as a node of a tree. Thus, these are equivalent:
add_column('sections', 'parent_id', :integer, :foreign_key => true)
is equivalent to
add_column('sections', 'parent_id', :integer)
add_foreign_key('sections', 'parent_id', 'sections', 'id')
A different foreign table name can be specified using :foreign_key => { :references => table_name }
, and a different column name can also be specified using :foreign_key => { :references => [table_name,column_name] }
Additional options :on_update
and :on_delete
can be specified, with values as described at ConnectionAdapters::ForeignKeyDefinition. For example:
add_column('comments', 'post', :integer, :references => 'posts', :on_delete => :cascade)
Global default values for :on_update
and :on_delete
can be specified in SchemaPlus.steup via, e.g., config.foreign_keys.on_update = :cascade
The constraint will have an automatic default name, but you can specify a constraint name using :foreign_key => { :name => "my_name" }
Automatic Foreign Key Constraints
SchemaPlus supports the convention of naming foreign key columns with a suffix of _id
. That is, if you define a column suffixed with _id
, SchemaPlus assumes that you want a foreign key constraint with default paramters. Thus, these two are equivalent:
add_column('posts', 'author_id', :integer)
add_column('posts', 'author_id', :integer, :foreign_key => true)
If you don’t want a foreign key constraint to be created, specify :foreign_key => false
. To disable automatic foreign key constraint creation globally, set config.foreign_keys.auto_create = false
in SchemaPlus.steup.
Shortcut options
As a shortcut (and for backwards compatibility), the options :references
, :on_update
, and :on_delete
can provided to add_column
directly instead of within a :foreign_key
hash.
The presence of option :references
implies the foreign key should be created, while :references => nil
is a shortcut for :foreign_key => false
Automatic Foreign Key Indexes
Since efficient use of foreign key constraints requires that the referencing column be indexed, SchemaPlus will automatically create an index for the column if it created a foreign key. Thus
add_column('widgets', 'color', :integer, :references => 'colors')
is equivalent to:
add_column('widgets', 'color', :integer, :references => 'colors', :index => true)
If you want to pass options to the index, you can explcitly pass index options, such as :index => :unique
.
If you don’t want an index to be created, specify :index => nil
. To disable automatic foreign key index creation globally, set config.foreign_keys.auto_index = false
in SchemaPlus.steup. (Note: If you’re using MySQL, it will automatically create an index for foreign keys if you don’t.)
123 124 125 126 127 |
# File 'lib/schema_plus/active_record/foreign_keys.rb', line 123 def add_column(table_name, column_name, type, = {}) () super (table_name, column_name, ) end |
#change_column(table_name, column_name, type, options = {}) ⇒ Object
Enhances ActiveRecord::Migration#change_column to support indexes and foreign keys same as add_column.
130 131 132 133 134 |
# File 'lib/schema_plus/active_record/foreign_keys.rb', line 130 def change_column(table_name, column_name, type, = {}) () super (table_name, column_name, ) end |