activerecord 4.1.8 → 4.2.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1165 -1591
- data/README.rdoc +15 -10
- data/lib/active_record/aggregations.rb +15 -8
- data/lib/active_record/association_relation.rb +13 -0
- data/lib/active_record/associations/alias_tracker.rb +3 -12
- data/lib/active_record/associations/association.rb +16 -4
- data/lib/active_record/associations/association_scope.rb +84 -43
- data/lib/active_record/associations/belongs_to_association.rb +28 -10
- data/lib/active_record/associations/builder/association.rb +16 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -29
- data/lib/active_record/associations/builder/collection_association.rb +5 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +9 -14
- data/lib/active_record/associations/builder/has_many.rb +1 -1
- data/lib/active_record/associations/builder/has_one.rb +2 -2
- data/lib/active_record/associations/builder/singular_association.rb +8 -1
- data/lib/active_record/associations/collection_association.rb +87 -30
- data/lib/active_record/associations/collection_proxy.rb +33 -35
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +83 -22
- data/lib/active_record/associations/has_many_through_association.rb +49 -26
- data/lib/active_record/associations/has_one_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -15
- data/lib/active_record/associations/join_dependency/join_part.rb +0 -1
- data/lib/active_record/associations/join_dependency.rb +26 -12
- data/lib/active_record/associations/preloader/association.rb +14 -10
- data/lib/active_record/associations/preloader/through_association.rb +4 -3
- data/lib/active_record/associations/preloader.rb +37 -26
- data/lib/active_record/associations/singular_association.rb +17 -2
- data/lib/active_record/associations/through_association.rb +16 -12
- data/lib/active_record/associations.rb +158 -49
- data/lib/active_record/attribute.rb +163 -0
- data/lib/active_record/attribute_assignment.rb +20 -12
- data/lib/active_record/attribute_decorators.rb +66 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +107 -43
- data/lib/active_record/attribute_methods/primary_key.rb +7 -8
- data/lib/active_record/attribute_methods/query.rb +1 -1
- data/lib/active_record/attribute_methods/read.rb +22 -59
- data/lib/active_record/attribute_methods/serialization.rb +16 -150
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -28
- data/lib/active_record/attribute_methods/write.rb +9 -24
- data/lib/active_record/attribute_methods.rb +57 -95
- data/lib/active_record/attribute_set/builder.rb +106 -0
- data/lib/active_record/attribute_set.rb +81 -0
- data/lib/active_record/attributes.rb +147 -0
- data/lib/active_record/autosave_association.rb +30 -12
- data/lib/active_record/base.rb +13 -24
- data/lib/active_record/callbacks.rb +6 -6
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +85 -53
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +52 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +60 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +39 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +139 -57
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -34
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +271 -74
- data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -118
- data/lib/active_record/connection_adapters/abstract_adapter.rb +177 -60
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +295 -141
- data/lib/active_record/connection_adapters/column.rb +29 -240
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -24
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +17 -33
- data/lib/active_record/connection_adapters/mysql_adapter.rb +68 -145
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
- data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -25
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -385
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +46 -136
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +134 -43
- data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -477
- data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -75
- data/lib/active_record/connection_handling.rb +1 -1
- data/lib/active_record/core.rb +163 -40
- data/lib/active_record/counter_cache.rb +60 -6
- data/lib/active_record/enum.rb +10 -12
- data/lib/active_record/errors.rb +53 -30
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixtures.rb +62 -74
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +35 -10
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/legacy_yaml_adapter.rb +30 -0
- data/lib/active_record/locking/optimistic.rb +46 -26
- data/lib/active_record/migration/command_recorder.rb +19 -2
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +79 -47
- data/lib/active_record/model_schema.rb +52 -58
- data/lib/active_record/nested_attributes.rb +18 -8
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/persistence.rb +48 -27
- data/lib/active_record/query_cache.rb +3 -3
- data/lib/active_record/querying.rb +10 -7
- data/lib/active_record/railtie.rb +19 -14
- data/lib/active_record/railties/databases.rake +55 -56
- data/lib/active_record/readonly_attributes.rb +0 -1
- data/lib/active_record/reflection.rb +281 -117
- data/lib/active_record/relation/batches.rb +0 -1
- data/lib/active_record/relation/calculations.rb +41 -37
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +71 -48
- data/lib/active_record/relation/merger.rb +39 -29
- data/lib/active_record/relation/predicate_builder/array_handler.rb +32 -13
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +42 -12
- data/lib/active_record/relation/query_methods.rb +130 -73
- data/lib/active_record/relation/spawn_methods.rb +10 -3
- data/lib/active_record/relation.rb +57 -25
- data/lib/active_record/result.rb +18 -7
- data/lib/active_record/sanitization.rb +12 -2
- data/lib/active_record/schema.rb +0 -1
- data/lib/active_record/schema_dumper.rb +59 -28
- data/lib/active_record/schema_migration.rb +5 -4
- data/lib/active_record/scoping/default.rb +6 -4
- data/lib/active_record/scoping/named.rb +4 -0
- data/lib/active_record/serializers/xml_serializer.rb +3 -7
- data/lib/active_record/statement_cache.rb +95 -10
- data/lib/active_record/store.rb +5 -5
- data/lib/active_record/tasks/database_tasks.rb +61 -8
- data/lib/active_record/tasks/mysql_database_tasks.rb +32 -17
- data/lib/active_record/tasks/postgresql_database_tasks.rb +20 -9
- data/lib/active_record/timestamp.rb +9 -7
- data/lib/active_record/transactions.rb +54 -28
- data/lib/active_record/type/big_integer.rb +13 -0
- data/lib/active_record/type/binary.rb +50 -0
- data/lib/active_record/type/boolean.rb +31 -0
- data/lib/active_record/type/date.rb +50 -0
- data/lib/active_record/type/date_time.rb +54 -0
- data/lib/active_record/type/decimal.rb +64 -0
- data/lib/active_record/type/decimal_without_scale.rb +11 -0
- data/lib/active_record/type/decorator.rb +14 -0
- data/lib/active_record/type/float.rb +19 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
- data/lib/active_record/type/integer.rb +59 -0
- data/lib/active_record/type/mutable.rb +16 -0
- data/lib/active_record/type/numeric.rb +36 -0
- data/lib/active_record/type/serialized.rb +62 -0
- data/lib/active_record/type/string.rb +40 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +26 -0
- data/lib/active_record/type/time_value.rb +38 -0
- data/lib/active_record/type/type_map.rb +64 -0
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type/value.rb +110 -0
- data/lib/active_record/type.rb +23 -0
- data/lib/active_record/validations/associated.rb +5 -3
- data/lib/active_record/validations/presence.rb +5 -3
- data/lib/active_record/validations/uniqueness.rb +24 -20
- data/lib/active_record/validations.rb +25 -19
- data/lib/active_record.rb +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
- metadata +66 -11
- data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/string/strip'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
class AbstractAdapter
|
@@ -13,9 +15,7 @@ module ActiveRecord
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def visit_AddColumn(o)
|
16
|
-
|
17
|
-
sql = "ADD #{quote_column_name(o.name)} #{sql_type}"
|
18
|
-
add_column_options!(sql, column_options(o))
|
18
|
+
"ADD #{accept(o)}"
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
@@ -23,10 +23,12 @@ module ActiveRecord
|
|
23
23
|
def visit_AlterTable(o)
|
24
24
|
sql = "ALTER TABLE #{quote_table_name(o.name)} "
|
25
25
|
sql << o.adds.map { |col| visit_AddColumn col }.join(' ')
|
26
|
+
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(' ')
|
27
|
+
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(' ')
|
26
28
|
end
|
27
29
|
|
28
30
|
def visit_ColumnDefinition(o)
|
29
|
-
sql_type = type_to_sql(o.type
|
31
|
+
sql_type = type_to_sql(o.type, o.limit, o.precision, o.scale)
|
30
32
|
column_sql = "#{quote_column_name(o.name)} #{sql_type}"
|
31
33
|
add_column_options!(column_sql, column_options(o)) unless o.primary_key?
|
32
34
|
column_sql
|
@@ -41,6 +43,21 @@ module ActiveRecord
|
|
41
43
|
create_sql
|
42
44
|
end
|
43
45
|
|
46
|
+
def visit_AddForeignKey(o)
|
47
|
+
sql = <<-SQL.strip_heredoc
|
48
|
+
ADD CONSTRAINT #{quote_column_name(o.name)}
|
49
|
+
FOREIGN KEY (#{quote_column_name(o.column)})
|
50
|
+
REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
|
51
|
+
SQL
|
52
|
+
sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete
|
53
|
+
sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update
|
54
|
+
sql
|
55
|
+
end
|
56
|
+
|
57
|
+
def visit_DropForeignKey(name)
|
58
|
+
"DROP CONSTRAINT #{quote_column_name(name)}"
|
59
|
+
end
|
60
|
+
|
44
61
|
def column_options(o)
|
45
62
|
column_options = {}
|
46
63
|
column_options[:null] = o.null unless o.null.nil?
|
@@ -77,6 +94,7 @@ module ActiveRecord
|
|
77
94
|
|
78
95
|
def quote_value(value, column)
|
79
96
|
column.sql_type ||= type_to_sql(column.type, column.limit, column.precision, column.scale)
|
97
|
+
column.cast_type ||= type_for_column(column)
|
80
98
|
|
81
99
|
@conn.quote(value, column)
|
82
100
|
end
|
@@ -84,6 +102,23 @@ module ActiveRecord
|
|
84
102
|
def options_include_default?(options)
|
85
103
|
options.include?(:default) && !(options[:null] == false && options[:default].nil?)
|
86
104
|
end
|
105
|
+
|
106
|
+
def action_sql(action, dependency)
|
107
|
+
case dependency
|
108
|
+
when :nullify then "ON #{action} SET NULL"
|
109
|
+
when :cascade then "ON #{action} CASCADE"
|
110
|
+
when :restrict then "ON #{action} RESTRICT"
|
111
|
+
else
|
112
|
+
raise ArgumentError, <<-MSG.strip_heredoc
|
113
|
+
'#{dependency}' is not supported for :on_update or :on_delete.
|
114
|
+
Supported values are: :nullify, :cascade, :restrict
|
115
|
+
MSG
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def type_for_column(column)
|
120
|
+
@conn.lookup_cast_type(column.sql_type)
|
121
|
+
end
|
87
122
|
end
|
88
123
|
end
|
89
124
|
end
|
@@ -15,7 +15,7 @@ module ActiveRecord
|
|
15
15
|
# are typically created by methods in TableDefinition, and added to the
|
16
16
|
# +columns+ attribute of said TableDefinition object, in order to be used
|
17
17
|
# for generating a number of table creation or table changing SQL statements.
|
18
|
-
class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key, :sql_type) #:nodoc:
|
18
|
+
class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key, :sql_type, :cast_type) #:nodoc:
|
19
19
|
|
20
20
|
def primary_key?
|
21
21
|
primary_key || type.to_sym == :primary_key
|
@@ -25,6 +25,49 @@ module ActiveRecord
|
|
25
25
|
class ChangeColumnDefinition < Struct.new(:column, :type, :options) #:nodoc:
|
26
26
|
end
|
27
27
|
|
28
|
+
class ForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
|
29
|
+
def name
|
30
|
+
options[:name]
|
31
|
+
end
|
32
|
+
|
33
|
+
def column
|
34
|
+
options[:column]
|
35
|
+
end
|
36
|
+
|
37
|
+
def primary_key
|
38
|
+
options[:primary_key] || default_primary_key
|
39
|
+
end
|
40
|
+
|
41
|
+
def on_delete
|
42
|
+
options[:on_delete]
|
43
|
+
end
|
44
|
+
|
45
|
+
def on_update
|
46
|
+
options[:on_update]
|
47
|
+
end
|
48
|
+
|
49
|
+
def custom_primary_key?
|
50
|
+
options[:primary_key] != default_primary_key
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def default_primary_key
|
55
|
+
"id"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
module TimestampDefaultDeprecation # :nodoc:
|
60
|
+
def emit_warning_if_null_unspecified(sym, options)
|
61
|
+
return if options.key?(:null)
|
62
|
+
|
63
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
64
|
+
`##{sym}` was called without specifying an option for `null`. In Rails 5,
|
65
|
+
this behavior will change to `null: false`. You should manually specify
|
66
|
+
`null: true` to prevent the behavior of your existing migrations from changing.
|
67
|
+
MSG
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
28
71
|
# Represents the schema of an SQL table in an abstract way. This class
|
29
72
|
# provides methods for manipulating the schema representation.
|
30
73
|
#
|
@@ -46,14 +89,17 @@ module ActiveRecord
|
|
46
89
|
# The table definitions
|
47
90
|
# The Columns are stored as a ColumnDefinition in the +columns+ attribute.
|
48
91
|
class TableDefinition
|
92
|
+
include TimestampDefaultDeprecation
|
93
|
+
|
49
94
|
# An array of ColumnDefinition objects, representing the column changes
|
50
95
|
# that have been defined.
|
51
96
|
attr_accessor :indexes
|
52
|
-
attr_reader :name, :temporary, :options, :as
|
97
|
+
attr_reader :name, :temporary, :options, :as, :foreign_keys
|
53
98
|
|
54
99
|
def initialize(types, name, temporary, options, as = nil)
|
55
100
|
@columns_hash = {}
|
56
101
|
@indexes = {}
|
102
|
+
@foreign_keys = []
|
57
103
|
@native = types
|
58
104
|
@temporary = temporary
|
59
105
|
@options = options
|
@@ -79,8 +125,8 @@ module ActiveRecord
|
|
79
125
|
# which is one of the following:
|
80
126
|
# <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
|
81
127
|
# <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>,
|
82
|
-
# <tt>:datetime</tt>, <tt>:
|
83
|
-
# <tt>:
|
128
|
+
# <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
|
129
|
+
# <tt>:binary</tt>, <tt>:boolean</tt>.
|
84
130
|
#
|
85
131
|
# You may use a type not in this list as long as it is supported by your
|
86
132
|
# database (for example, "polygon" in MySQL), but this will not be database
|
@@ -99,9 +145,11 @@ module ActiveRecord
|
|
99
145
|
# Specifies the precision for a <tt>:decimal</tt> column.
|
100
146
|
# * <tt>:scale</tt> -
|
101
147
|
# Specifies the scale for a <tt>:decimal</tt> column.
|
148
|
+
# * <tt>:index</tt> -
|
149
|
+
# Create an index for the column. Can be either <tt>true</tt> or an options hash.
|
102
150
|
#
|
103
|
-
#
|
104
|
-
#
|
151
|
+
# Note: The precision is the total number of significant digits
|
152
|
+
# and the scale is the number of digits that can be stored following
|
105
153
|
# the decimal point. For example, the number 123.45 has a precision of 5
|
106
154
|
# and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
|
107
155
|
# range from -999.99 to 999.99.
|
@@ -123,17 +171,8 @@ module ActiveRecord
|
|
123
171
|
# Default is (38,0).
|
124
172
|
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
|
125
173
|
# Default unknown.
|
126
|
-
# * Firebird: <tt>:precision</tt> [1..18], <tt>:scale</tt> [0..18].
|
127
|
-
# Default (9,0). Internal types NUMERIC and DECIMAL have different
|
128
|
-
# storage rules, decimal being better.
|
129
|
-
# * FrontBase?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
130
|
-
# Default (38,0). WARNING Max <tt>:precision</tt>/<tt>:scale</tt> for
|
131
|
-
# NUMERIC is 19, and DECIMAL is 38.
|
132
174
|
# * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
133
175
|
# Default (38,0).
|
134
|
-
# * Sybase: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
135
|
-
# Default (38,0).
|
136
|
-
# * OpenBase?: Documentation unclear. Claims storage in <tt>double</tt>.
|
137
176
|
#
|
138
177
|
# This method returns <tt>self</tt>.
|
139
178
|
#
|
@@ -172,20 +211,23 @@ module ActiveRecord
|
|
172
211
|
# What can be written like this with the regular calls to column:
|
173
212
|
#
|
174
213
|
# create_table :products do |t|
|
175
|
-
# t.column :shop_id,
|
176
|
-
# t.column :creator_id,
|
177
|
-
# t.column :
|
178
|
-
# t.column :
|
179
|
-
# t.column :
|
180
|
-
# t.column :
|
214
|
+
# t.column :shop_id, :integer
|
215
|
+
# t.column :creator_id, :integer
|
216
|
+
# t.column :item_number, :string
|
217
|
+
# t.column :name, :string, default: "Untitled"
|
218
|
+
# t.column :value, :string, default: "Untitled"
|
219
|
+
# t.column :created_at, :datetime
|
220
|
+
# t.column :updated_at, :datetime
|
181
221
|
# end
|
222
|
+
# add_index :products, :item_number
|
182
223
|
#
|
183
224
|
# can also be written as follows using the short-hand:
|
184
225
|
#
|
185
226
|
# create_table :products do |t|
|
186
227
|
# t.integer :shop_id, :creator_id
|
228
|
+
# t.string :item_number, index: true
|
187
229
|
# t.string :name, :value, default: "Untitled"
|
188
|
-
# t.timestamps
|
230
|
+
# t.timestamps null: false
|
189
231
|
# end
|
190
232
|
#
|
191
233
|
# There's a short-hand method for each of the type values declared at the top. And then there's
|
@@ -214,11 +256,14 @@ module ActiveRecord
|
|
214
256
|
def column(name, type, options = {})
|
215
257
|
name = name.to_s
|
216
258
|
type = type.to_sym
|
259
|
+
options = options.dup
|
217
260
|
|
218
|
-
if
|
261
|
+
if @columns_hash[name] && @columns_hash[name].primary_key?
|
219
262
|
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
220
263
|
end
|
221
264
|
|
265
|
+
index_options = options.delete(:index)
|
266
|
+
index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
|
222
267
|
@columns_hash[name] = new_column_definition(name, type, options)
|
223
268
|
self
|
224
269
|
end
|
@@ -227,7 +272,7 @@ module ActiveRecord
|
|
227
272
|
@columns_hash.delete name.to_s
|
228
273
|
end
|
229
274
|
|
230
|
-
[:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
|
275
|
+
[:string, :text, :integer, :bigint, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
|
231
276
|
define_method column_type do |*args|
|
232
277
|
options = args.extract_options!
|
233
278
|
column_names = args
|
@@ -243,34 +288,58 @@ module ActiveRecord
|
|
243
288
|
indexes[column_name] = options
|
244
289
|
end
|
245
290
|
|
291
|
+
def foreign_key(table_name, options = {}) # :nodoc:
|
292
|
+
foreign_keys.push([table_name, options])
|
293
|
+
end
|
294
|
+
|
246
295
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
247
|
-
# <tt>:updated_at</tt> to the table.
|
296
|
+
# <tt>:updated_at</tt> to the table. See SchemaStatements#add_timestamps
|
297
|
+
#
|
298
|
+
# t.timestamps null: false
|
248
299
|
def timestamps(*args)
|
249
300
|
options = args.extract_options!
|
301
|
+
emit_warning_if_null_unspecified(:timestamps, options)
|
250
302
|
column(:created_at, :datetime, options)
|
251
303
|
column(:updated_at, :datetime, options)
|
252
304
|
end
|
253
305
|
|
306
|
+
# Adds a reference.
|
307
|
+
#
|
308
|
+
# t.references(:user)
|
309
|
+
# t.belongs_to(:supplier, foreign_key: true)
|
310
|
+
#
|
311
|
+
# See SchemaStatements#add_reference for details of the options you can use.
|
254
312
|
def references(*args)
|
255
313
|
options = args.extract_options!
|
256
314
|
polymorphic = options.delete(:polymorphic)
|
257
315
|
index_options = options.delete(:index)
|
316
|
+
foreign_key_options = options.delete(:foreign_key)
|
317
|
+
type = options.delete(:type) || :integer
|
318
|
+
|
319
|
+
if polymorphic && foreign_key_options
|
320
|
+
raise ArgumentError, "Cannot add a foreign key on a polymorphic relation"
|
321
|
+
end
|
322
|
+
|
258
323
|
args.each do |col|
|
259
|
-
column("#{col}_id",
|
324
|
+
column("#{col}_id", type, options)
|
260
325
|
column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
|
261
|
-
index(polymorphic ? %w(id
|
326
|
+
index(polymorphic ? %w(type id).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
|
327
|
+
if foreign_key_options
|
328
|
+
to_table = Base.pluralize_table_names ? col.to_s.pluralize : col.to_s
|
329
|
+
foreign_key(to_table, foreign_key_options.is_a?(Hash) ? foreign_key_options : {})
|
330
|
+
end
|
262
331
|
end
|
263
332
|
end
|
264
333
|
alias :belongs_to :references
|
265
334
|
|
266
335
|
def new_column_definition(name, type, options) # :nodoc:
|
336
|
+
type = aliased_types(type.to_s, type)
|
267
337
|
column = create_column_definition name, type
|
268
338
|
limit = options.fetch(:limit) do
|
269
339
|
native[type][:limit] if native[type].is_a?(Hash)
|
270
340
|
end
|
271
341
|
|
272
342
|
column.limit = limit
|
273
|
-
column.array = options[:array] if column.respond_to?(:array)
|
274
343
|
column.precision = options[:precision]
|
275
344
|
column.scale = options[:scale]
|
276
345
|
column.default = options[:default]
|
@@ -286,26 +355,37 @@ module ActiveRecord
|
|
286
355
|
ColumnDefinition.new name, type
|
287
356
|
end
|
288
357
|
|
289
|
-
def primary_key_column_name
|
290
|
-
primary_key_column = columns.detect { |c| c.primary_key? }
|
291
|
-
primary_key_column && primary_key_column.name
|
292
|
-
end
|
293
|
-
|
294
358
|
def native
|
295
359
|
@native
|
296
360
|
end
|
361
|
+
|
362
|
+
def aliased_types(name, fallback)
|
363
|
+
'timestamp' == name ? :datetime : fallback
|
364
|
+
end
|
297
365
|
end
|
298
366
|
|
299
367
|
class AlterTable # :nodoc:
|
300
368
|
attr_reader :adds
|
369
|
+
attr_reader :foreign_key_adds
|
370
|
+
attr_reader :foreign_key_drops
|
301
371
|
|
302
372
|
def initialize(td)
|
303
373
|
@td = td
|
304
374
|
@adds = []
|
375
|
+
@foreign_key_adds = []
|
376
|
+
@foreign_key_drops = []
|
305
377
|
end
|
306
378
|
|
307
379
|
def name; @td.name; end
|
308
380
|
|
381
|
+
def add_foreign_key(to_table, options)
|
382
|
+
@foreign_key_adds << ForeignKeyDefinition.new(name, to_table, options)
|
383
|
+
end
|
384
|
+
|
385
|
+
def drop_foreign_key(name)
|
386
|
+
@foreign_key_drops << name
|
387
|
+
end
|
388
|
+
|
309
389
|
def add_column(name, type, options)
|
310
390
|
name = name.to_s
|
311
391
|
type = type.to_sym
|
@@ -347,8 +427,10 @@ module ActiveRecord
|
|
347
427
|
# end
|
348
428
|
#
|
349
429
|
class Table
|
430
|
+
attr_reader :name
|
431
|
+
|
350
432
|
def initialize(table_name, base)
|
351
|
-
@
|
433
|
+
@name = table_name
|
352
434
|
@base = base
|
353
435
|
end
|
354
436
|
|
@@ -358,12 +440,12 @@ module ActiveRecord
|
|
358
440
|
# ====== Creating a simple column
|
359
441
|
# t.column(:name, :string)
|
360
442
|
def column(column_name, type, options = {})
|
361
|
-
@base.add_column(
|
443
|
+
@base.add_column(name, column_name, type, options)
|
362
444
|
end
|
363
445
|
|
364
446
|
# Checks to see if a column exists. See SchemaStatements#column_exists?
|
365
447
|
def column_exists?(column_name, type = nil, options = {})
|
366
|
-
@base.column_exists?(
|
448
|
+
@base.column_exists?(name, column_name, type, options)
|
367
449
|
end
|
368
450
|
|
369
451
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
@@ -376,26 +458,26 @@ module ActiveRecord
|
|
376
458
|
# ====== Creating a named index
|
377
459
|
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
|
378
460
|
def index(column_name, options = {})
|
379
|
-
@base.add_index(
|
461
|
+
@base.add_index(name, column_name, options)
|
380
462
|
end
|
381
463
|
|
382
464
|
# Checks to see if an index exists. See SchemaStatements#index_exists?
|
383
465
|
def index_exists?(column_name, options = {})
|
384
|
-
@base.index_exists?(
|
466
|
+
@base.index_exists?(name, column_name, options)
|
385
467
|
end
|
386
468
|
|
387
469
|
# Renames the given index on the table.
|
388
470
|
#
|
389
471
|
# t.rename_index(:user_id, :account_id)
|
390
472
|
def rename_index(index_name, new_index_name)
|
391
|
-
@base.rename_index(
|
473
|
+
@base.rename_index(name, index_name, new_index_name)
|
392
474
|
end
|
393
475
|
|
394
476
|
# Adds timestamps (+created_at+ and +updated_at+) columns to the table. See SchemaStatements#add_timestamps
|
395
477
|
#
|
396
|
-
# t.timestamps
|
397
|
-
def timestamps
|
398
|
-
@base.add_timestamps(
|
478
|
+
# t.timestamps null: false
|
479
|
+
def timestamps(options = {})
|
480
|
+
@base.add_timestamps(name, options)
|
399
481
|
end
|
400
482
|
|
401
483
|
# Changes the column's definition according to the new options.
|
@@ -404,7 +486,7 @@ module ActiveRecord
|
|
404
486
|
# t.change(:name, :string, limit: 80)
|
405
487
|
# t.change(:description, :text)
|
406
488
|
def change(column_name, type, options = {})
|
407
|
-
@base.change_column(
|
489
|
+
@base.change_column(name, column_name, type, options)
|
408
490
|
end
|
409
491
|
|
410
492
|
# Sets a new default value for a column. See SchemaStatements#change_column_default
|
@@ -412,7 +494,7 @@ module ActiveRecord
|
|
412
494
|
# t.change_default(:qualification, 'new')
|
413
495
|
# t.change_default(:authorized, 1)
|
414
496
|
def change_default(column_name, default)
|
415
|
-
@base.change_column_default(
|
497
|
+
@base.change_column_default(name, column_name, default)
|
416
498
|
end
|
417
499
|
|
418
500
|
# Removes the column(s) from the table definition.
|
@@ -420,7 +502,7 @@ module ActiveRecord
|
|
420
502
|
# t.remove(:qualification)
|
421
503
|
# t.remove(:qualification, :experience)
|
422
504
|
def remove(*column_names)
|
423
|
-
@base.remove_columns(
|
505
|
+
@base.remove_columns(name, *column_names)
|
424
506
|
end
|
425
507
|
|
426
508
|
# Removes the given index from the table.
|
@@ -434,33 +516,33 @@ module ActiveRecord
|
|
434
516
|
# ====== Remove the index named by_branch_party in the table_name table
|
435
517
|
# t.remove_index name: :by_branch_party
|
436
518
|
def remove_index(options = {})
|
437
|
-
@base.remove_index(
|
519
|
+
@base.remove_index(name, options)
|
438
520
|
end
|
439
521
|
|
440
522
|
# Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
|
441
523
|
#
|
442
524
|
# t.remove_timestamps
|
443
|
-
def remove_timestamps
|
444
|
-
@base.remove_timestamps(
|
525
|
+
def remove_timestamps(options = {})
|
526
|
+
@base.remove_timestamps(name, options)
|
445
527
|
end
|
446
528
|
|
447
529
|
# Renames a column.
|
448
530
|
#
|
449
531
|
# t.rename(:description, :name)
|
450
532
|
def rename(column_name, new_column_name)
|
451
|
-
@base.rename_column(
|
533
|
+
@base.rename_column(name, column_name, new_column_name)
|
452
534
|
end
|
453
535
|
|
454
|
-
# Adds a reference.
|
455
|
-
# <tt>references</tt> and <tt>belongs_to</tt> are acceptable.
|
536
|
+
# Adds a reference.
|
456
537
|
#
|
457
538
|
# t.references(:user)
|
458
|
-
# t.belongs_to(:supplier,
|
539
|
+
# t.belongs_to(:supplier, foreign_key: true)
|
459
540
|
#
|
541
|
+
# See SchemaStatements#add_reference for details of the options you can use.
|
460
542
|
def references(*args)
|
461
543
|
options = args.extract_options!
|
462
544
|
args.each do |ref_name|
|
463
|
-
@base.add_reference(
|
545
|
+
@base.add_reference(name, ref_name, options)
|
464
546
|
end
|
465
547
|
end
|
466
548
|
alias :belongs_to :references
|
@@ -471,10 +553,11 @@ module ActiveRecord
|
|
471
553
|
# t.remove_references(:user)
|
472
554
|
# t.remove_belongs_to(:supplier, polymorphic: true)
|
473
555
|
#
|
556
|
+
# See SchemaStatements#remove_reference
|
474
557
|
def remove_references(*args)
|
475
558
|
options = args.extract_options!
|
476
559
|
args.each do |ref_name|
|
477
|
-
@base.remove_reference(
|
560
|
+
@base.remove_reference(name, ref_name, options)
|
478
561
|
end
|
479
562
|
end
|
480
563
|
alias :remove_belongs_to :remove_references
|
@@ -486,8 +569,8 @@ module ActiveRecord
|
|
486
569
|
[:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
|
487
570
|
define_method column_type do |*args|
|
488
571
|
options = args.extract_options!
|
489
|
-
args.each do |
|
490
|
-
@base.add_column(
|
572
|
+
args.each do |column_name|
|
573
|
+
@base.add_column(name, column_name, column_type, options)
|
491
574
|
end
|
492
575
|
end
|
493
576
|
end
|
@@ -497,6 +580,5 @@ module ActiveRecord
|
|
497
580
|
@base.native_database_types
|
498
581
|
end
|
499
582
|
end
|
500
|
-
|
501
583
|
end
|
502
584
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'ipaddr'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module ConnectionAdapters # :nodoc:
|
5
3
|
# The goal of this module is to move Adapter specific column
|
@@ -10,7 +8,7 @@ module ActiveRecord
|
|
10
8
|
module ColumnDumper
|
11
9
|
def column_spec(column, types)
|
12
10
|
spec = prepare_column_options(column, types)
|
13
|
-
(spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k
|
11
|
+
(spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k}: ")}
|
14
12
|
spec
|
15
13
|
end
|
16
14
|
|
@@ -20,19 +18,17 @@ module ActiveRecord
|
|
20
18
|
def prepare_column_options(column, types)
|
21
19
|
spec = {}
|
22
20
|
spec[:name] = column.name.inspect
|
21
|
+
spec[:type] = column.type.to_s
|
22
|
+
spec[:null] = 'false' unless column.null
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
spec[:type] = if column.type == :integer && /^(numeric|decimal)/ =~ column.sql_type
|
27
|
-
'decimal'
|
28
|
-
else
|
29
|
-
column.type.to_s
|
30
|
-
end
|
31
|
-
spec[:limit] = column.limit.inspect if column.limit != types[column.type][:limit] && spec[:type] != 'decimal'
|
24
|
+
limit = column.limit || types[column.type][:limit]
|
25
|
+
spec[:limit] = limit.inspect if limit
|
32
26
|
spec[:precision] = column.precision.inspect if column.precision
|
33
27
|
spec[:scale] = column.scale.inspect if column.scale
|
34
|
-
|
35
|
-
|
28
|
+
|
29
|
+
default = schema_default(column) if column.has_default?
|
30
|
+
spec[:default] = default unless default.nil?
|
31
|
+
|
36
32
|
spec
|
37
33
|
end
|
38
34
|
|
@@ -43,28 +39,12 @@ module ActiveRecord
|
|
43
39
|
|
44
40
|
private
|
45
41
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
when Date, DateTime, Time
|
51
|
-
"'#{value.to_s(:db)}'"
|
52
|
-
when Range
|
53
|
-
# infinity dumps as Infinity, which causes uninitialized constant error
|
54
|
-
value.inspect.gsub('Infinity', '::Float::INFINITY')
|
55
|
-
when IPAddr
|
56
|
-
subnet_mask = value.instance_variable_get(:@mask_addr)
|
57
|
-
|
58
|
-
# If the subnet mask is equal to /32, don't output it
|
59
|
-
if subnet_mask == (2**32 - 1)
|
60
|
-
"\"#{value.to_s}\""
|
61
|
-
else
|
62
|
-
"\"#{value.to_s}/#{subnet_mask.to_s(2).count('1')}\""
|
63
|
-
end
|
64
|
-
else
|
65
|
-
value.inspect
|
66
|
-
end
|
42
|
+
def schema_default(column)
|
43
|
+
default = column.type_cast_from_database(column.default)
|
44
|
+
unless default.nil?
|
45
|
+
column.type_cast_for_schema(default)
|
67
46
|
end
|
47
|
+
end
|
68
48
|
end
|
69
49
|
end
|
70
50
|
end
|