activerecord 4.1.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +776 -1330
  3. data/README.rdoc +15 -10
  4. data/lib/active_record/aggregations.rb +12 -8
  5. data/lib/active_record/association_relation.rb +4 -0
  6. data/lib/active_record/associations/alias_tracker.rb +14 -13
  7. data/lib/active_record/associations/association.rb +2 -2
  8. data/lib/active_record/associations/association_scope.rb +83 -43
  9. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  10. data/lib/active_record/associations/builder/association.rb +15 -4
  11. data/lib/active_record/associations/builder/belongs_to.rb +7 -29
  12. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +9 -6
  13. data/lib/active_record/associations/builder/has_many.rb +1 -1
  14. data/lib/active_record/associations/builder/has_one.rb +2 -2
  15. data/lib/active_record/associations/builder/singular_association.rb +8 -1
  16. data/lib/active_record/associations/collection_association.rb +66 -29
  17. data/lib/active_record/associations/collection_proxy.rb +22 -26
  18. data/lib/active_record/associations/has_many_association.rb +65 -18
  19. data/lib/active_record/associations/has_many_through_association.rb +55 -27
  20. data/lib/active_record/associations/has_one_association.rb +0 -1
  21. data/lib/active_record/associations/join_dependency/join_association.rb +19 -15
  22. data/lib/active_record/associations/join_dependency/join_part.rb +0 -1
  23. data/lib/active_record/associations/join_dependency.rb +20 -12
  24. data/lib/active_record/associations/preloader/association.rb +34 -11
  25. data/lib/active_record/associations/preloader/through_association.rb +4 -3
  26. data/lib/active_record/associations/preloader.rb +49 -59
  27. data/lib/active_record/associations/singular_association.rb +25 -4
  28. data/lib/active_record/associations/through_association.rb +23 -14
  29. data/lib/active_record/associations.rb +171 -42
  30. data/lib/active_record/attribute.rb +149 -0
  31. data/lib/active_record/attribute_assignment.rb +18 -10
  32. data/lib/active_record/attribute_decorators.rb +66 -0
  33. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -2
  34. data/lib/active_record/attribute_methods/dirty.rb +98 -44
  35. data/lib/active_record/attribute_methods/primary_key.rb +14 -8
  36. data/lib/active_record/attribute_methods/query.rb +1 -1
  37. data/lib/active_record/attribute_methods/read.rb +22 -59
  38. data/lib/active_record/attribute_methods/serialization.rb +37 -147
  39. data/lib/active_record/attribute_methods/time_zone_conversion.rb +34 -28
  40. data/lib/active_record/attribute_methods/write.rb +14 -21
  41. data/lib/active_record/attribute_methods.rb +67 -94
  42. data/lib/active_record/attribute_set/builder.rb +86 -0
  43. data/lib/active_record/attribute_set.rb +77 -0
  44. data/lib/active_record/attributes.rb +139 -0
  45. data/lib/active_record/autosave_association.rb +45 -38
  46. data/lib/active_record/base.rb +10 -20
  47. data/lib/active_record/callbacks.rb +7 -7
  48. data/lib/active_record/coders/json.rb +13 -0
  49. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +78 -52
  50. data/lib/active_record/connection_adapters/abstract/database_statements.rb +38 -59
  51. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -0
  52. data/lib/active_record/connection_adapters/abstract/quoting.rb +59 -55
  53. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -5
  54. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +126 -54
  55. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -34
  56. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +198 -64
  57. data/lib/active_record/connection_adapters/abstract/transaction.rb +126 -114
  58. data/lib/active_record/connection_adapters/abstract_adapter.rb +154 -55
  59. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +240 -135
  60. data/lib/active_record/connection_adapters/column.rb +28 -239
  61. data/lib/active_record/connection_adapters/connection_specification.rb +16 -25
  62. data/lib/active_record/connection_adapters/mysql2_adapter.rb +20 -22
  63. data/lib/active_record/connection_adapters/mysql_adapter.rb +65 -149
  64. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
  65. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  66. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +39 -27
  67. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +99 -0
  68. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  69. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  70. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +14 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  73. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +27 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  78. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  79. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  80. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +97 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -374
  93. data/lib/active_record/connection_adapters/postgresql/quoting.rb +55 -135
  94. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  96. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +127 -38
  97. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  98. data/lib/active_record/connection_adapters/postgresql_adapter.rb +220 -466
  99. data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
  100. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +66 -61
  101. data/lib/active_record/connection_handling.rb +3 -3
  102. data/lib/active_record/core.rb +143 -32
  103. data/lib/active_record/counter_cache.rb +60 -7
  104. data/lib/active_record/enum.rb +10 -11
  105. data/lib/active_record/errors.rb +49 -27
  106. data/lib/active_record/explain.rb +1 -1
  107. data/lib/active_record/fixtures.rb +56 -70
  108. data/lib/active_record/gem_version.rb +2 -2
  109. data/lib/active_record/inheritance.rb +35 -10
  110. data/lib/active_record/integration.rb +4 -4
  111. data/lib/active_record/locking/optimistic.rb +35 -17
  112. data/lib/active_record/log_subscriber.rb +1 -1
  113. data/lib/active_record/migration/command_recorder.rb +19 -2
  114. data/lib/active_record/migration/join_table.rb +1 -1
  115. data/lib/active_record/migration.rb +52 -49
  116. data/lib/active_record/model_schema.rb +49 -57
  117. data/lib/active_record/nested_attributes.rb +7 -7
  118. data/lib/active_record/null_relation.rb +19 -5
  119. data/lib/active_record/persistence.rb +50 -31
  120. data/lib/active_record/query_cache.rb +3 -3
  121. data/lib/active_record/querying.rb +10 -7
  122. data/lib/active_record/railtie.rb +14 -11
  123. data/lib/active_record/railties/databases.rake +56 -54
  124. data/lib/active_record/readonly_attributes.rb +0 -1
  125. data/lib/active_record/reflection.rb +286 -102
  126. data/lib/active_record/relation/batches.rb +0 -1
  127. data/lib/active_record/relation/calculations.rb +39 -31
  128. data/lib/active_record/relation/delegation.rb +2 -2
  129. data/lib/active_record/relation/finder_methods.rb +80 -36
  130. data/lib/active_record/relation/merger.rb +25 -30
  131. data/lib/active_record/relation/predicate_builder/array_handler.rb +31 -13
  132. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  133. data/lib/active_record/relation/predicate_builder.rb +11 -10
  134. data/lib/active_record/relation/query_methods.rb +141 -55
  135. data/lib/active_record/relation/spawn_methods.rb +3 -0
  136. data/lib/active_record/relation.rb +69 -30
  137. data/lib/active_record/result.rb +18 -7
  138. data/lib/active_record/sanitization.rb +12 -2
  139. data/lib/active_record/schema.rb +0 -1
  140. data/lib/active_record/schema_dumper.rb +58 -26
  141. data/lib/active_record/schema_migration.rb +11 -0
  142. data/lib/active_record/scoping/default.rb +8 -7
  143. data/lib/active_record/scoping/named.rb +4 -0
  144. data/lib/active_record/serializers/xml_serializer.rb +3 -7
  145. data/lib/active_record/statement_cache.rb +95 -10
  146. data/lib/active_record/store.rb +19 -10
  147. data/lib/active_record/tasks/database_tasks.rb +73 -7
  148. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -2
  149. data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
  150. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  151. data/lib/active_record/timestamp.rb +11 -9
  152. data/lib/active_record/transactions.rb +37 -21
  153. data/lib/active_record/type/big_integer.rb +13 -0
  154. data/lib/active_record/type/binary.rb +50 -0
  155. data/lib/active_record/type/boolean.rb +30 -0
  156. data/lib/active_record/type/date.rb +46 -0
  157. data/lib/active_record/type/date_time.rb +43 -0
  158. data/lib/active_record/type/decimal.rb +40 -0
  159. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  160. data/lib/active_record/type/decorator.rb +14 -0
  161. data/lib/active_record/type/float.rb +19 -0
  162. data/lib/active_record/type/hash_lookup_type_map.rb +17 -0
  163. data/lib/active_record/type/integer.rb +55 -0
  164. data/lib/active_record/type/mutable.rb +16 -0
  165. data/lib/active_record/type/numeric.rb +36 -0
  166. data/lib/active_record/type/serialized.rb +56 -0
  167. data/lib/active_record/type/string.rb +36 -0
  168. data/lib/active_record/type/text.rb +11 -0
  169. data/lib/active_record/type/time.rb +26 -0
  170. data/lib/active_record/type/time_value.rb +38 -0
  171. data/lib/active_record/type/type_map.rb +64 -0
  172. data/lib/active_record/type/unsigned_integer.rb +15 -0
  173. data/lib/active_record/type/value.rb +101 -0
  174. data/lib/active_record/type.rb +23 -0
  175. data/lib/active_record/validations/associated.rb +5 -3
  176. data/lib/active_record/validations/presence.rb +6 -4
  177. data/lib/active_record/validations/uniqueness.rb +11 -17
  178. data/lib/active_record/validations.rb +25 -19
  179. data/lib/active_record.rb +3 -0
  180. data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
  181. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +4 -1
  182. data/lib/rails/generators/active_record/migration/templates/migration.rb +6 -0
  183. data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
  184. metadata +65 -10
  185. data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -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) #: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(options)
61
+ return if options.key?(:null)
62
+
63
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
64
+ `#timestamp` 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,6 +89,8 @@ 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
@@ -79,8 +124,8 @@ module ActiveRecord
79
124
  # which is one of the following:
80
125
  # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
81
126
  # <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>,
82
- # <tt>:datetime</tt>, <tt>:timestamp</tt>, <tt>:time</tt>,
83
- # <tt>:date</tt>, <tt>:binary</tt>, <tt>:boolean</tt>.
127
+ # <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
128
+ # <tt>:binary</tt>, <tt>:boolean</tt>.
84
129
  #
85
130
  # You may use a type not in this list as long as it is supported by your
86
131
  # database (for example, "polygon" in MySQL), but this will not be database
@@ -99,9 +144,11 @@ module ActiveRecord
99
144
  # Specifies the precision for a <tt>:decimal</tt> column.
100
145
  # * <tt>:scale</tt> -
101
146
  # Specifies the scale for a <tt>:decimal</tt> column.
147
+ # * <tt>:index</tt> -
148
+ # Create an index for the column. Can be either <tt>true</tt> or an options hash.
102
149
  #
103
- # For clarity's sake: the precision is the number of significant digits,
104
- # while the scale is the number of digits that can be stored following
150
+ # Note: The precision is the total number of significant digits
151
+ # and the scale is the number of digits that can be stored following
105
152
  # the decimal point. For example, the number 123.45 has a precision of 5
106
153
  # and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
107
154
  # range from -999.99 to 999.99.
@@ -123,17 +170,8 @@ module ActiveRecord
123
170
  # Default is (38,0).
124
171
  # * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
125
172
  # 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
173
  # * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
133
174
  # 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
175
  #
138
176
  # This method returns <tt>self</tt>.
139
177
  #
@@ -172,20 +210,23 @@ module ActiveRecord
172
210
  # What can be written like this with the regular calls to column:
173
211
  #
174
212
  # create_table :products do |t|
175
- # t.column :shop_id, :integer
176
- # t.column :creator_id, :integer
177
- # t.column :name, :string, default: "Untitled"
178
- # t.column :value, :string, default: "Untitled"
179
- # t.column :created_at, :datetime
180
- # t.column :updated_at, :datetime
213
+ # t.column :shop_id, :integer
214
+ # t.column :creator_id, :integer
215
+ # t.column :item_number, :string
216
+ # t.column :name, :string, default: "Untitled"
217
+ # t.column :value, :string, default: "Untitled"
218
+ # t.column :created_at, :datetime
219
+ # t.column :updated_at, :datetime
181
220
  # end
221
+ # add_index :products, :item_number
182
222
  #
183
223
  # can also be written as follows using the short-hand:
184
224
  #
185
225
  # create_table :products do |t|
186
226
  # t.integer :shop_id, :creator_id
227
+ # t.string :item_number, index: true
187
228
  # t.string :name, :value, default: "Untitled"
188
- # t.timestamps
229
+ # t.timestamps null: false
189
230
  # end
190
231
  #
191
232
  # There's a short-hand method for each of the type values declared at the top. And then there's
@@ -215,10 +256,12 @@ module ActiveRecord
215
256
  name = name.to_s
216
257
  type = type.to_sym
217
258
 
218
- if primary_key_column_name == name
259
+ if @columns_hash[name] && @columns_hash[name].primary_key?
219
260
  raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
220
261
  end
221
262
 
263
+ index_options = options.delete(:index)
264
+ index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
222
265
  @columns_hash[name] = new_column_definition(name, type, options)
223
266
  self
224
267
  end
@@ -227,7 +270,7 @@ module ActiveRecord
227
270
  @columns_hash.delete name.to_s
228
271
  end
229
272
 
230
- [:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
273
+ [:string, :text, :integer, :bigint, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
231
274
  define_method column_type do |*args|
232
275
  options = args.extract_options!
233
276
  column_names = args
@@ -244,33 +287,46 @@ module ActiveRecord
244
287
  end
245
288
 
246
289
  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
247
- # <tt>:updated_at</tt> to the table.
290
+ # <tt>:updated_at</tt> to the table. See SchemaStatements#add_timestamps
291
+ #
292
+ # t.timestamps null: false
248
293
  def timestamps(*args)
249
294
  options = args.extract_options!
295
+ emit_warning_if_null_unspecified(options)
250
296
  column(:created_at, :datetime, options)
251
297
  column(:updated_at, :datetime, options)
252
298
  end
253
299
 
300
+ # Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
301
+ # <tt>references</tt> and <tt>belongs_to</tt> are acceptable. The reference column will be an +integer+
302
+ # by default, the <tt>:type</tt> option can be used to specify a different type.
303
+ #
304
+ # t.references(:user)
305
+ # t.references(:user, type: "string")
306
+ # t.belongs_to(:supplier, polymorphic: true)
307
+ #
308
+ # See SchemaStatements#add_reference
254
309
  def references(*args)
255
310
  options = args.extract_options!
256
311
  polymorphic = options.delete(:polymorphic)
257
312
  index_options = options.delete(:index)
313
+ type = options.delete(:type) || :integer
258
314
  args.each do |col|
259
- column("#{col}_id", :integer, options)
315
+ column("#{col}_id", type, options)
260
316
  column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
261
- index(polymorphic ? %w(id type).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
317
+ index(polymorphic ? %w(type id).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
262
318
  end
263
319
  end
264
320
  alias :belongs_to :references
265
321
 
266
322
  def new_column_definition(name, type, options) # :nodoc:
323
+ type = aliased_types(type.to_s, type)
267
324
  column = create_column_definition name, type
268
325
  limit = options.fetch(:limit) do
269
326
  native[type][:limit] if native[type].is_a?(Hash)
270
327
  end
271
328
 
272
329
  column.limit = limit
273
- column.array = options[:array] if column.respond_to?(:array)
274
330
  column.precision = options[:precision]
275
331
  column.scale = options[:scale]
276
332
  column.default = options[:default]
@@ -286,26 +342,37 @@ module ActiveRecord
286
342
  ColumnDefinition.new name, type
287
343
  end
288
344
 
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
345
  def native
295
346
  @native
296
347
  end
348
+
349
+ def aliased_types(name, fallback)
350
+ 'timestamp' == name ? :datetime : fallback
351
+ end
297
352
  end
298
353
 
299
354
  class AlterTable # :nodoc:
300
355
  attr_reader :adds
356
+ attr_reader :foreign_key_adds
357
+ attr_reader :foreign_key_drops
301
358
 
302
359
  def initialize(td)
303
360
  @td = td
304
361
  @adds = []
362
+ @foreign_key_adds = []
363
+ @foreign_key_drops = []
305
364
  end
306
365
 
307
366
  def name; @td.name; end
308
367
 
368
+ def add_foreign_key(to_table, options)
369
+ @foreign_key_adds << ForeignKeyDefinition.new(name, to_table, options)
370
+ end
371
+
372
+ def drop_foreign_key(name)
373
+ @foreign_key_drops << name
374
+ end
375
+
309
376
  def add_column(name, type, options)
310
377
  name = name.to_s
311
378
  type = type.to_sym
@@ -347,8 +414,10 @@ module ActiveRecord
347
414
  # end
348
415
  #
349
416
  class Table
417
+ attr_reader :name
418
+
350
419
  def initialize(table_name, base)
351
- @table_name = table_name
420
+ @name = table_name
352
421
  @base = base
353
422
  end
354
423
 
@@ -358,12 +427,12 @@ module ActiveRecord
358
427
  # ====== Creating a simple column
359
428
  # t.column(:name, :string)
360
429
  def column(column_name, type, options = {})
361
- @base.add_column(@table_name, column_name, type, options)
430
+ @base.add_column(name, column_name, type, options)
362
431
  end
363
432
 
364
433
  # Checks to see if a column exists. See SchemaStatements#column_exists?
365
434
  def column_exists?(column_name, type = nil, options = {})
366
- @base.column_exists?(@table_name, column_name, type, options)
435
+ @base.column_exists?(name, column_name, type, options)
367
436
  end
368
437
 
369
438
  # Adds a new index to the table. +column_name+ can be a single Symbol, or
@@ -376,26 +445,26 @@ module ActiveRecord
376
445
  # ====== Creating a named index
377
446
  # t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
378
447
  def index(column_name, options = {})
379
- @base.add_index(@table_name, column_name, options)
448
+ @base.add_index(name, column_name, options)
380
449
  end
381
450
 
382
451
  # Checks to see if an index exists. See SchemaStatements#index_exists?
383
452
  def index_exists?(column_name, options = {})
384
- @base.index_exists?(@table_name, column_name, options)
453
+ @base.index_exists?(name, column_name, options)
385
454
  end
386
455
 
387
456
  # Renames the given index on the table.
388
457
  #
389
458
  # t.rename_index(:user_id, :account_id)
390
459
  def rename_index(index_name, new_index_name)
391
- @base.rename_index(@table_name, index_name, new_index_name)
460
+ @base.rename_index(name, index_name, new_index_name)
392
461
  end
393
462
 
394
463
  # Adds timestamps (+created_at+ and +updated_at+) columns to the table. See SchemaStatements#add_timestamps
395
464
  #
396
- # t.timestamps
397
- def timestamps
398
- @base.add_timestamps(@table_name)
465
+ # t.timestamps null: false
466
+ def timestamps(options = {})
467
+ @base.add_timestamps(name, options)
399
468
  end
400
469
 
401
470
  # Changes the column's definition according to the new options.
@@ -404,7 +473,7 @@ module ActiveRecord
404
473
  # t.change(:name, :string, limit: 80)
405
474
  # t.change(:description, :text)
406
475
  def change(column_name, type, options = {})
407
- @base.change_column(@table_name, column_name, type, options)
476
+ @base.change_column(name, column_name, type, options)
408
477
  end
409
478
 
410
479
  # Sets a new default value for a column. See SchemaStatements#change_column_default
@@ -412,7 +481,7 @@ module ActiveRecord
412
481
  # t.change_default(:qualification, 'new')
413
482
  # t.change_default(:authorized, 1)
414
483
  def change_default(column_name, default)
415
- @base.change_column_default(@table_name, column_name, default)
484
+ @base.change_column_default(name, column_name, default)
416
485
  end
417
486
 
418
487
  # Removes the column(s) from the table definition.
@@ -420,7 +489,7 @@ module ActiveRecord
420
489
  # t.remove(:qualification)
421
490
  # t.remove(:qualification, :experience)
422
491
  def remove(*column_names)
423
- @base.remove_columns(@table_name, *column_names)
492
+ @base.remove_columns(name, *column_names)
424
493
  end
425
494
 
426
495
  # Removes the given index from the table.
@@ -434,33 +503,36 @@ module ActiveRecord
434
503
  # ====== Remove the index named by_branch_party in the table_name table
435
504
  # t.remove_index name: :by_branch_party
436
505
  def remove_index(options = {})
437
- @base.remove_index(@table_name, options)
506
+ @base.remove_index(name, options)
438
507
  end
439
508
 
440
509
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
441
510
  #
442
511
  # t.remove_timestamps
443
- def remove_timestamps
444
- @base.remove_timestamps(@table_name)
512
+ def remove_timestamps(options = {})
513
+ @base.remove_timestamps(name, options)
445
514
  end
446
515
 
447
516
  # Renames a column.
448
517
  #
449
518
  # t.rename(:description, :name)
450
519
  def rename(column_name, new_column_name)
451
- @base.rename_column(@table_name, column_name, new_column_name)
520
+ @base.rename_column(name, column_name, new_column_name)
452
521
  end
453
522
 
454
523
  # Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
455
- # <tt>references</tt> and <tt>belongs_to</tt> are acceptable.
524
+ # <tt>references</tt> and <tt>belongs_to</tt> are acceptable. The reference column will be an +integer+
525
+ # by default, the <tt>:type</tt> option can be used to specify a different type.
456
526
  #
457
527
  # t.references(:user)
528
+ # t.references(:user, type: "string")
458
529
  # t.belongs_to(:supplier, polymorphic: true)
459
530
  #
531
+ # See SchemaStatements#add_reference
460
532
  def references(*args)
461
533
  options = args.extract_options!
462
534
  args.each do |ref_name|
463
- @base.add_reference(@table_name, ref_name, options)
535
+ @base.add_reference(name, ref_name, options)
464
536
  end
465
537
  end
466
538
  alias :belongs_to :references
@@ -471,10 +543,11 @@ module ActiveRecord
471
543
  # t.remove_references(:user)
472
544
  # t.remove_belongs_to(:supplier, polymorphic: true)
473
545
  #
546
+ # See SchemaStatements#remove_reference
474
547
  def remove_references(*args)
475
548
  options = args.extract_options!
476
549
  args.each do |ref_name|
477
- @base.remove_reference(@table_name, ref_name, options)
550
+ @base.remove_reference(name, ref_name, options)
478
551
  end
479
552
  end
480
553
  alias :remove_belongs_to :remove_references
@@ -486,8 +559,8 @@ module ActiveRecord
486
559
  [:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
487
560
  define_method column_type do |*args|
488
561
  options = args.extract_options!
489
- args.each do |name|
490
- @base.add_column(@table_name, name, column_type, options)
562
+ args.each do |column_name|
563
+ @base.add_column(name, column_name, column_type, options)
491
564
  end
492
565
  end
493
566
  end
@@ -497,6 +570,5 @@ module ActiveRecord
497
570
  @base.native_database_types
498
571
  end
499
572
  end
500
-
501
573
  end
502
574
  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.to_s}: ")}
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
- # AR has an optimization which handles zero-scale decimals as integers. This
25
- # code ensures that the dumper still dumps the column as a decimal.
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
- spec[:null] = 'false' unless column.null
35
- spec[:default] = default_string(column.default) if column.has_default?
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
- def default_string(value)
47
- case value
48
- when BigDecimal
49
- value.to_s
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