Module: SchemaPlus::ActiveRecord::Migration::ClassMethods
- Defined in:
- lib/schema_plus/active_record/migration.rb
Overview
SchemaPlus extends ActiveRecord::Migration with the following enhancements.
Instance Method Summary collapse
-
#add_column(table_name, column_name, type, options = {}) ⇒ Object
Enhances ActiveRecord::Migration#add_column to support indexes and foreign keys, with automatic creation.
-
#add_foreign_key(table_name, column_names, references_table_name, references_column_names, options = {}) ⇒ Object
Define a foreign key constraint.
-
#change_column(table_name, column_name, type, options = {}) ⇒ Object
Enhances ActiveRecord::Migration#change_column to support indexes and foreign keys same as add_column.
-
#create_view(view_name, definition) ⇒ Object
Create a new view, given its name and SQL definition.
-
#drop_view(view_name) ⇒ Object
Drop the named view.
-
#get_references(table_name, column_name, options = {}, config = nil) ⇒ Object
Determines referenced table and column.
-
#remove_foreign_key(table_name, foreign_key_name) ⇒ Object
Remove a foreign key constraint.
Instance Method Details
#add_column(table_name, column_name, type, options = {}) ⇒ Object
Enhances ActiveRecord::Migration#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 :references
option takes the name of a table to reference in a foreign key constraint. For example:
add_column('widgets', 'color', :integer, :references => 'colors')
is equivalent to
add_column('widgets', 'color', :integer)
add_foreign_key('widgets', 'color', 'colors', 'id')
The foreign column name defaults to id
, but a different column can be specified using :references => [table_name,column_name]
Additional options :on_update
and :on_delete
can be spcified, 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
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 an implied :references to a table whose name is the column name prefix, pluralized. For example, these are equivalent:
add_column('posts', 'author_id', :integer)
add_column('posts', 'author_id', :integer, :references => 'authors')
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)
add_column('sections', 'parent_id', :integer, :references => 'sections')
If the implicit :references
value isn’t what you want (e.g., the table name isn’t pluralized), you can explicitly specify :references
and it will override the implicit value.
If you don’t want a foreign key constraint to be created, specify :references => nil
. To disable automatic foreign key constraint creation globally, set config.foreign_keys.auto_create = false
in SchemaPlus.steup.
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.)
147 148 149 150 |
# File 'lib/schema_plus/active_record/migration.rb', line 147 def add_column(table_name, column_name, type, = {}) super (table_name, column_name, ) end |
#add_foreign_key(table_name, column_names, references_table_name, references_column_names, options = {}) ⇒ 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.)
32 33 34 |
# File 'lib/schema_plus/active_record/migration.rb', line 32 def add_foreign_key(table_name, column_names, references_table_name, references_column_names, = {}) connection.add_foreign_key(table_name, column_names, references_table_name, references_column_names, ) 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.
153 154 155 156 157 |
# File 'lib/schema_plus/active_record/migration.rb', line 153 def change_column(table_name, column_name, type, = {}) super remove_foreign_key_if_exists(table_name, column_name) (table_name, column_name, ) end |
#create_view(view_name, definition) ⇒ Object
Create a new view, given its name and SQL definition
15 16 17 |
# File 'lib/schema_plus/active_record/migration.rb', line 15 def create_view(view_name, definition) connection.create_view(view_name, definition) end |
#drop_view(view_name) ⇒ Object
Drop the named view
20 21 22 |
# File 'lib/schema_plus/active_record/migration.rb', line 20 def drop_view(view_name) connection.drop_view(view_name) end |
#get_references(table_name, column_name, options = {}, config = nil) ⇒ Object
Determines referenced table and column. Used in migrations.
If auto_create is true:
get_references('comments', 'post_id') # => ['posts', 'id']
And if column_name
is parent_id it references to the same table
get_references('pages', 'parent_id') # => ['pages', 'id']
If :references option is given, it is used (whether or not auto_create is true)
get_references('widgets', 'main_page_id', :references => 'pages'))
# => ['pages', 'id']
Also the referenced id column may be specified:
get_references('addresses', 'member_id', :references => ['users', 'uuid'])
# => ['users', 'uuid']
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/schema_plus/active_record/migration.rb', line 175 def get_references(table_name, column_name, = {}, config=nil) #:nodoc: column_name = column_name.to_s if .has_key?(:references) references = [:references] references = [references, :id] unless references.nil? || references.is_a?(Array) references elsif (config || SchemaPlus.config).foreign_keys.auto_create? && !ActiveRecord::Schema.defining? if column_name == 'parent_id' [table_name, :id] elsif column_name =~ /^(.*)_id$/ determined_table_name = ActiveRecord::Base.pluralize_table_names ? $1.to_s.pluralize : $1 [determined_table_name, :id] end end end |
#remove_foreign_key(table_name, foreign_key_name) ⇒ Object
Remove a foreign key constraint
(NOTE: Sqlite3 does not support altering a table to remove foreign-key constraints. If you’re using Sqlite3, this method will raise an error.)
41 42 43 |
# File 'lib/schema_plus/active_record/migration.rb', line 41 def remove_foreign_key(table_name, foreign_key_name) connection.remove_foreign_key(table_name, foreign_key_name) end |