aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb')
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb161
1 files changed, 53 insertions, 108 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 429445540d..e2ef56798b 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -1,7 +1,3 @@
-require 'date'
-require 'bigdecimal'
-require 'bigdecimal/util'
-
module ActiveRecord
module ConnectionAdapters #:nodoc:
# Abstract representation of an index definition on a table. Instances of
@@ -27,6 +23,9 @@ module ActiveRecord
class ChangeColumnDefinition < Struct.new(:column, :name) #:nodoc:
end
+ class PrimaryKeyDefinition < Struct.new(:name) # :nodoc:
+ end
+
class ForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
def name
options[:name]
@@ -124,23 +123,29 @@ module ActiveRecord
end
def foreign_key_options
- as_options(foreign_key)
+ as_options(foreign_key).merge(column: column_name)
end
def columns
- result = [["#{name}_id", type, options]]
+ result = [[column_name, type, options]]
if polymorphic
result.unshift(["#{name}_type", :string, polymorphic_options])
end
result
end
+ def column_name
+ "#{name}_id"
+ end
+
def column_names
columns.map(&:first)
end
def foreign_table_name
- Base.pluralize_table_names ? name.to_s.pluralize : name
+ foreign_key_options.fetch(:to_table) do
+ Base.pluralize_table_names ? name.to_s.pluralize : name
+ end
end
end
@@ -182,7 +187,7 @@ module ActiveRecord
# Represents the schema of an SQL table in an abstract way. This class
# provides methods for manipulating the schema representation.
#
- # Inside migration files, the +t+ object in +create_table+
+ # Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
# is actually of this type:
#
# class SomeMigration < ActiveRecord::Migration
@@ -198,19 +203,20 @@ module ActiveRecord
# end
#
# The table definitions
- # The Columns are stored as a ColumnDefinition in the +columns+ attribute.
+ # The Columns are stored as a ColumnDefinition in the #columns attribute.
class TableDefinition
include ColumnMethods
# An array of ColumnDefinition objects, representing the column changes
# that have been defined.
attr_accessor :indexes
- attr_reader :name, :temporary, :options, :as, :foreign_keys
+ attr_reader :name, :temporary, :options, :as, :foreign_keys, :native
def initialize(types, name, temporary, options, as = nil)
@columns_hash = {}
@indexes = {}
@foreign_keys = {}
+ @primary_keys = nil
@native = types
@temporary = temporary
@options = options
@@ -218,6 +224,12 @@ module ActiveRecord
@name = name
end
+ def primary_keys(name = nil) # :nodoc:
+ @primary_keys = PrimaryKeyDefinition.new(name) if name
+ @primary_keys
+ end
+
+ # Returns an array of ColumnDefinition objects for the columns of the table.
def columns; @columns_hash.values; end
# Returns a ColumnDefinition for the column with name +name+.
@@ -226,90 +238,23 @@ module ActiveRecord
end
# Instantiates a new column for the table.
- # The +type+ parameter is normally one of the migrations native types,
- # which is one of the following:
- # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
- # <tt>:integer</tt>, <tt>:bigint</tt>, <tt>:float</tt>, <tt>:decimal</tt>,
- # <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
- # <tt>:binary</tt>, <tt>:boolean</tt>.
- #
- # You may use a type not in this list as long as it is supported by your
- # database (for example, "polygon" in MySQL), but this will not be database
- # agnostic and should usually be avoided.
- #
- # Available options are (none of these exists by default):
- # * <tt>:limit</tt> -
- # Requests a maximum column length. This is number of characters for <tt>:string</tt> and
- # <tt>:text</tt> columns and number of bytes for <tt>:binary</tt> and <tt>:integer</tt> columns.
- # * <tt>:default</tt> -
- # The column's default value. Use nil for NULL.
- # * <tt>:null</tt> -
- # Allows or disallows +NULL+ values in the column. This option could
- # have been named <tt>:null_allowed</tt>.
- # * <tt>:precision</tt> -
- # Specifies the precision for a <tt>:decimal</tt> column.
- # * <tt>:scale</tt> -
- # Specifies the scale for a <tt>:decimal</tt> column.
+ # See {connection.add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column]
+ # for available options.
+ #
+ # Additional options are:
# * <tt>:index</tt> -
# Create an index for the column. Can be either <tt>true</tt> or an options hash.
#
- # Note: The precision is the total number of significant digits
- # and the scale is the number of digits that can be stored following
- # the decimal point. For example, the number 123.45 has a precision of 5
- # and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
- # range from -999.99 to 999.99.
- #
- # Please be aware of different RDBMS implementations behavior with
- # <tt>:decimal</tt> columns:
- # * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
- # <tt>:precision</tt>, and makes no comments about the requirements of
- # <tt>:precision</tt>.
- # * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
- # Default is (10,0).
- # * PostgreSQL: <tt>:precision</tt> [1..infinity],
- # <tt>:scale</tt> [0..infinity]. No default.
- # * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
- # Internal storage as strings. No default.
- # * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
- # but the maximum supported <tt>:precision</tt> is 16. No default.
- # * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
- # Default is (38,0).
- # * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
- # Default unknown.
- # * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
- # Default (38,0).
- #
# This method returns <tt>self</tt>.
#
# == Examples
- # # Assuming +td+ is an instance of TableDefinition
- # td.column(:granted, :boolean)
- # # granted BOOLEAN
- #
- # td.column(:picture, :binary, limit: 2.megabytes)
- # # => picture BLOB(2097152)
- #
- # td.column(:sales_stage, :string, limit: 20, default: 'new', null: false)
- # # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
- #
- # td.column(:bill_gates_money, :decimal, precision: 15, scale: 2)
- # # => bill_gates_money DECIMAL(15,2)
- #
- # td.column(:sensor_reading, :decimal, precision: 30, scale: 20)
- # # => sensor_reading DECIMAL(30,20)
#
- # # While <tt>:scale</tt> defaults to zero on most databases, it
- # # probably wouldn't hurt to include it.
- # td.column(:huge_integer, :decimal, precision: 30)
- # # => huge_integer DECIMAL(30)
- #
- # # Defines a column with a database-specific type.
- # td.column(:foo, 'polygon')
- # # => foo polygon
+ # # Assuming +td+ is an instance of TableDefinition
+ # td.column(:granted, :boolean, index: true)
#
# == Short-hand examples
#
- # Instead of calling +column+ directly, you can also work with the short-hand definitions for the default types.
+ # Instead of calling #column directly, you can also work with the short-hand definitions for the default types.
# They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
# in a single statement.
#
@@ -341,7 +286,8 @@ module ActiveRecord
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
# column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
# options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
- # will also create an index, similar to calling <tt>add_index</tt>. So what can be written like this:
+ # will also create an index, similar to calling {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index].
+ # So what can be written like this:
#
# create_table :taggings do |t|
# t.integer :tag_id, :tagger_id, :taggable_id
@@ -373,6 +319,8 @@ module ActiveRecord
self
end
+ # remove the column +name+ from the table.
+ # remove_column(:account_id)
def remove_column(name)
@columns_hash.delete name.to_s
end
@@ -390,7 +338,7 @@ module ActiveRecord
end
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
- # <tt>:updated_at</tt> to the table. See SchemaStatements#add_timestamps
+ # <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
#
# t.timestamps null: false
def timestamps(*args)
@@ -407,7 +355,7 @@ module ActiveRecord
# t.references(:user)
# t.belongs_to(:supplier, foreign_key: true)
#
- # See SchemaStatements#add_reference for details of the options you can use.
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
def references(*args, **options)
args.each do |col|
ReferenceDefinition.new(col, **options).add_to(self)
@@ -440,10 +388,6 @@ module ActiveRecord
ColumnDefinition.new name, type
end
- def native
- @native
- end
-
def aliased_types(name, fallback)
'timestamp' == name ? :datetime : fallback
end
@@ -479,7 +423,7 @@ module ActiveRecord
end
# Represents an SQL table in an abstract way for updating a table.
- # Also see TableDefinition and SchemaStatements#create_table
+ # Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
#
# Available transformations are:
#
@@ -536,7 +480,7 @@ module ActiveRecord
#
# t.string(:name) unless t.column_exists?(:name, :string)
#
- # See SchemaStatements#column_exists?
+ # See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
def column_exists?(column_name, type = nil, options = {})
@base.column_exists?(name, column_name, type, options)
end
@@ -548,7 +492,7 @@ module ActiveRecord
# t.index([:branch_id, :party_id], unique: true)
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
#
- # See SchemaStatements#add_index for details of the options you can use.
+ # See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
def index(column_name, options = {})
@base.add_index(name, column_name, options)
end
@@ -559,7 +503,7 @@ module ActiveRecord
# t.index(:branch_id)
# end
#
- # See SchemaStatements#index_exists?
+ # See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
def index_exists?(column_name, options = {})
@base.index_exists?(name, column_name, options)
end
@@ -568,7 +512,7 @@ module ActiveRecord
#
# t.rename_index(:user_id, :account_id)
#
- # See SchemaStatements#rename_index
+ # See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index]
def rename_index(index_name, new_index_name)
@base.rename_index(name, index_name, new_index_name)
end
@@ -577,7 +521,7 @@ module ActiveRecord
#
# t.timestamps(null: false)
#
- # See SchemaStatements#add_timestamps
+ # See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
def timestamps(options = {})
@base.add_timestamps(name, options)
end
@@ -596,10 +540,11 @@ module ActiveRecord
#
# t.change_default(:qualification, 'new')
# t.change_default(:authorized, 1)
+ # t.change_default(:status, from: nil, to: "draft")
#
- # See SchemaStatements#change_column_default
- def change_default(column_name, default)
- @base.change_column_default(name, column_name, default)
+ # See {connection.change_column_default}[rdoc-ref:SchemaStatements#change_column_default]
+ def change_default(column_name, default_or_changes)
+ @base.change_column_default(name, column_name, default_or_changes)
end
# Removes the column(s) from the table definition.
@@ -607,7 +552,7 @@ module ActiveRecord
# t.remove(:qualification)
# t.remove(:qualification, :experience)
#
- # See SchemaStatements#remove_columns
+ # See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
def remove(*column_names)
@base.remove_columns(name, *column_names)
end
@@ -618,7 +563,7 @@ module ActiveRecord
# t.remove_index(column: [:branch_id, :party_id])
# t.remove_index(name: :by_branch_party)
#
- # See SchemaStatements#remove_index
+ # See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
def remove_index(options = {})
@base.remove_index(name, options)
end
@@ -627,7 +572,7 @@ module ActiveRecord
#
# t.remove_timestamps
#
- # See SchemaStatements#remove_timestamps
+ # See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
def remove_timestamps(options = {})
@base.remove_timestamps(name, options)
end
@@ -636,7 +581,7 @@ module ActiveRecord
#
# t.rename(:description, :name)
#
- # See SchemaStatements#rename_column
+ # See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column]
def rename(column_name, new_column_name)
@base.rename_column(name, column_name, new_column_name)
end
@@ -646,7 +591,7 @@ module ActiveRecord
# t.references(:user)
# t.belongs_to(:supplier, foreign_key: true)
#
- # See SchemaStatements#add_reference for details of the options you can use.
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
def references(*args)
options = args.extract_options!
args.each do |ref_name|
@@ -660,7 +605,7 @@ module ActiveRecord
# t.remove_references(:user)
# t.remove_belongs_to(:supplier, polymorphic: true)
#
- # See SchemaStatements#remove_reference
+ # See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
def remove_references(*args)
options = args.extract_options!
args.each do |ref_name|
@@ -673,7 +618,7 @@ module ActiveRecord
#
# t.foreign_key(:authors)
#
- # See SchemaStatements#add_foreign_key
+ # See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
def foreign_key(*args) # :nodoc:
@base.add_foreign_key(name, *args)
end
@@ -682,7 +627,7 @@ module ActiveRecord
#
# t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
#
- # See SchemaStatements#foreign_key_exists?
+ # See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
def foreign_key_exists?(*args) # :nodoc:
@base.foreign_key_exists?(name, *args)
end