activerecord 3.2.22.5 → 4.0.0.beta1

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 (162) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1024 -543
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +20 -29
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +55 -44
  7. data/lib/active_record/aggregations.rb +40 -34
  8. data/lib/active_record/associations.rb +204 -276
  9. data/lib/active_record/associations/alias_tracker.rb +1 -1
  10. data/lib/active_record/associations/association.rb +30 -35
  11. data/lib/active_record/associations/association_scope.rb +40 -40
  12. data/lib/active_record/associations/belongs_to_association.rb +15 -2
  13. data/lib/active_record/associations/builder/association.rb +81 -28
  14. data/lib/active_record/associations/builder/belongs_to.rb +35 -57
  15. data/lib/active_record/associations/builder/collection_association.rb +54 -40
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -64
  18. data/lib/active_record/associations/builder/has_one.rb +13 -50
  19. data/lib/active_record/associations/builder/singular_association.rb +13 -13
  20. data/lib/active_record/associations/collection_association.rb +92 -88
  21. data/lib/active_record/associations/collection_proxy.rb +913 -63
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -10
  23. data/lib/active_record/associations/has_many_association.rb +35 -9
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -14
  25. data/lib/active_record/associations/has_one_association.rb +33 -13
  26. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  27. data/lib/active_record/associations/join_dependency.rb +2 -2
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -22
  29. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  30. data/lib/active_record/associations/join_helper.rb +1 -11
  31. data/lib/active_record/associations/preloader.rb +14 -17
  32. data/lib/active_record/associations/preloader/association.rb +29 -33
  33. data/lib/active_record/associations/preloader/collection_association.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +1 -1
  35. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  36. data/lib/active_record/associations/preloader/has_one.rb +1 -1
  37. data/lib/active_record/associations/preloader/through_association.rb +13 -17
  38. data/lib/active_record/associations/singular_association.rb +11 -11
  39. data/lib/active_record/associations/through_association.rb +2 -2
  40. data/lib/active_record/attribute_assignment.rb +133 -153
  41. data/lib/active_record/attribute_methods.rb +196 -93
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
  43. data/lib/active_record/attribute_methods/dirty.rb +31 -28
  44. data/lib/active_record/attribute_methods/primary_key.rb +38 -30
  45. data/lib/active_record/attribute_methods/query.rb +5 -4
  46. data/lib/active_record/attribute_methods/read.rb +62 -91
  47. data/lib/active_record/attribute_methods/serialization.rb +97 -66
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -45
  49. data/lib/active_record/attribute_methods/write.rb +32 -39
  50. data/lib/active_record/autosave_association.rb +56 -70
  51. data/lib/active_record/base.rb +53 -450
  52. data/lib/active_record/callbacks.rb +53 -18
  53. data/lib/active_record/coders/yaml_column.rb +11 -9
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +353 -197
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -131
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -19
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +23 -3
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +101 -91
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +59 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +225 -96
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +99 -46
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +114 -36
  65. data/lib/active_record/connection_adapters/column.rb +46 -24
  66. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  67. data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -32
  68. data/lib/active_record/connection_adapters/mysql_adapter.rb +181 -64
  69. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
  70. data/lib/active_record/connection_adapters/postgresql/cast.rb +132 -0
  71. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid.rb +347 -0
  73. data/lib/active_record/connection_adapters/postgresql/quoting.rb +158 -0
  74. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  75. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +448 -0
  76. data/lib/active_record/connection_adapters/postgresql_adapter.rb +454 -885
  77. data/lib/active_record/connection_adapters/schema_cache.rb +48 -16
  78. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +574 -13
  79. data/lib/active_record/connection_handling.rb +98 -0
  80. data/lib/active_record/core.rb +428 -0
  81. data/lib/active_record/counter_cache.rb +106 -108
  82. data/lib/active_record/dynamic_matchers.rb +110 -63
  83. data/lib/active_record/errors.rb +25 -8
  84. data/lib/active_record/explain.rb +8 -58
  85. data/lib/active_record/explain_subscriber.rb +6 -3
  86. data/lib/active_record/fixture_set/file.rb +56 -0
  87. data/lib/active_record/fixtures.rb +146 -148
  88. data/lib/active_record/inheritance.rb +77 -59
  89. data/lib/active_record/integration.rb +5 -5
  90. data/lib/active_record/locale/en.yml +8 -1
  91. data/lib/active_record/locking/optimistic.rb +38 -42
  92. data/lib/active_record/locking/pessimistic.rb +4 -4
  93. data/lib/active_record/log_subscriber.rb +19 -9
  94. data/lib/active_record/migration.rb +318 -153
  95. data/lib/active_record/migration/command_recorder.rb +90 -31
  96. data/lib/active_record/migration/join_table.rb +15 -0
  97. data/lib/active_record/model_schema.rb +69 -92
  98. data/lib/active_record/nested_attributes.rb +113 -148
  99. data/lib/active_record/null_relation.rb +65 -0
  100. data/lib/active_record/persistence.rb +188 -97
  101. data/lib/active_record/query_cache.rb +18 -36
  102. data/lib/active_record/querying.rb +19 -15
  103. data/lib/active_record/railtie.rb +91 -36
  104. data/lib/active_record/railties/console_sandbox.rb +0 -2
  105. data/lib/active_record/railties/controller_runtime.rb +2 -2
  106. data/lib/active_record/railties/databases.rake +90 -309
  107. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  108. data/lib/active_record/readonly_attributes.rb +7 -3
  109. data/lib/active_record/reflection.rb +72 -56
  110. data/lib/active_record/relation.rb +241 -157
  111. data/lib/active_record/relation/batches.rb +25 -22
  112. data/lib/active_record/relation/calculations.rb +143 -121
  113. data/lib/active_record/relation/delegation.rb +96 -18
  114. data/lib/active_record/relation/finder_methods.rb +117 -183
  115. data/lib/active_record/relation/merger.rb +133 -0
  116. data/lib/active_record/relation/predicate_builder.rb +90 -42
  117. data/lib/active_record/relation/query_methods.rb +666 -136
  118. data/lib/active_record/relation/spawn_methods.rb +43 -150
  119. data/lib/active_record/result.rb +33 -6
  120. data/lib/active_record/sanitization.rb +24 -50
  121. data/lib/active_record/schema.rb +19 -12
  122. data/lib/active_record/schema_dumper.rb +31 -39
  123. data/lib/active_record/schema_migration.rb +36 -0
  124. data/lib/active_record/scoping.rb +0 -124
  125. data/lib/active_record/scoping/default.rb +48 -45
  126. data/lib/active_record/scoping/named.rb +74 -103
  127. data/lib/active_record/serialization.rb +6 -2
  128. data/lib/active_record/serializers/xml_serializer.rb +9 -15
  129. data/lib/active_record/store.rb +119 -15
  130. data/lib/active_record/tasks/database_tasks.rb +158 -0
  131. data/lib/active_record/tasks/mysql_database_tasks.rb +138 -0
  132. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  133. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  134. data/lib/active_record/test_case.rb +61 -38
  135. data/lib/active_record/timestamp.rb +8 -9
  136. data/lib/active_record/transactions.rb +65 -51
  137. data/lib/active_record/validations.rb +17 -15
  138. data/lib/active_record/validations/associated.rb +20 -14
  139. data/lib/active_record/validations/presence.rb +65 -0
  140. data/lib/active_record/validations/uniqueness.rb +93 -52
  141. data/lib/active_record/version.rb +4 -4
  142. data/lib/rails/generators/active_record.rb +3 -5
  143. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -7
  144. data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
  145. data/lib/rails/generators/active_record/model/model_generator.rb +4 -3
  146. data/lib/rails/generators/active_record/model/templates/model.rb +1 -6
  147. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  148. metadata +53 -46
  149. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  150. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  151. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  152. data/lib/active_record/dynamic_finder_match.rb +0 -68
  153. data/lib/active_record/dynamic_scope_match.rb +0 -23
  154. data/lib/active_record/fixtures/file.rb +0 -65
  155. data/lib/active_record/identity_map.rb +0 -162
  156. data/lib/active_record/observer.rb +0 -121
  157. data/lib/active_record/session_store.rb +0 -360
  158. data/lib/rails/generators/active_record/migration.rb +0 -15
  159. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  160. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  161. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  162. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,4 +1,3 @@
1
- require 'active_support/core_ext/object/blank'
2
1
  require 'date'
3
2
  require 'set'
4
3
  require 'bigdecimal'
@@ -6,7 +5,10 @@ require 'bigdecimal/util'
6
5
 
7
6
  module ActiveRecord
8
7
  module ConnectionAdapters #:nodoc:
9
- class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders) #:nodoc:
8
+ # Abstract representation of an index definition on a table. Instances of
9
+ # this type are typically created and returned by methods in database
10
+ # adapters. e.g. ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#indexes
11
+ class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where) #:nodoc:
10
12
  end
11
13
 
12
14
  # Abstract representation of a column definition. Instances of this type
@@ -20,7 +22,7 @@ module ActiveRecord
20
22
  end
21
23
 
22
24
  def sql_type
23
- base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
25
+ base.type_to_sql(type.to_sym, limit, precision, scale)
24
26
  end
25
27
 
26
28
  def to_sql
@@ -42,8 +44,8 @@ module ActiveRecord
42
44
  # Represents the schema of an SQL table in an abstract way. This class
43
45
  # provides methods for manipulating the schema representation.
44
46
  #
45
- # Inside migration files, the +t+ object in +create_table+
46
- # is actually of this type:
47
+ # Inside migration files, the +t+ object in +create_table+ and
48
+ # +change_table+ is actually of this type:
47
49
  #
48
50
  # class SomeMigration < ActiveRecord::Migration
49
51
  # def up
@@ -62,11 +64,12 @@ module ActiveRecord
62
64
  class TableDefinition
63
65
  # An array of ColumnDefinition objects, representing the column changes
64
66
  # that have been defined.
65
- attr_accessor :columns
67
+ attr_accessor :columns, :indexes
66
68
 
67
69
  def initialize(base)
68
70
  @columns = []
69
71
  @columns_hash = {}
72
+ @indexes = {}
70
73
  @base = base
71
74
  end
72
75
 
@@ -158,21 +161,21 @@ module ActiveRecord
158
161
  # td.column(:granted, :boolean)
159
162
  # # granted BOOLEAN
160
163
  #
161
- # td.column(:picture, :binary, :limit => 2.megabytes)
164
+ # td.column(:picture, :binary, limit: 2.megabytes)
162
165
  # # => picture BLOB(2097152)
163
166
  #
164
- # td.column(:sales_stage, :string, :limit => 20, :default => 'new', :null => false)
167
+ # td.column(:sales_stage, :string, limit: 20, default: 'new', null: false)
165
168
  # # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
166
169
  #
167
- # td.column(:bill_gates_money, :decimal, :precision => 15, :scale => 2)
170
+ # td.column(:bill_gates_money, :decimal, precision: 15, scale: 2)
168
171
  # # => bill_gates_money DECIMAL(15,2)
169
172
  #
170
- # td.column(:sensor_reading, :decimal, :precision => 30, :scale => 20)
173
+ # td.column(:sensor_reading, :decimal, precision: 30, scale: 20)
171
174
  # # => sensor_reading DECIMAL(30,20)
172
175
  #
173
176
  # # While <tt>:scale</tt> defaults to zero on most databases, it
174
177
  # # probably wouldn't hurt to include it.
175
- # td.column(:huge_integer, :decimal, :precision => 30)
178
+ # td.column(:huge_integer, :decimal, precision: 30)
176
179
  # # => huge_integer DECIMAL(30)
177
180
  #
178
181
  # # Defines a column with a database-specific type.
@@ -187,20 +190,20 @@ module ActiveRecord
187
190
  #
188
191
  # What can be written like this with the regular calls to column:
189
192
  #
190
- # create_table "products", :force => true do |t|
191
- # t.column "shop_id", :integer
192
- # t.column "creator_id", :integer
193
- # t.column "name", :string, :default => "Untitled"
194
- # t.column "value", :string, :default => "Untitled"
195
- # t.column "created_at", :datetime
196
- # t.column "updated_at", :datetime
193
+ # create_table :products do |t|
194
+ # t.column :shop_id, :integer
195
+ # t.column :creator_id, :integer
196
+ # t.column :name, :string, default: "Untitled"
197
+ # t.column :value, :string, default: "Untitled"
198
+ # t.column :created_at, :datetime
199
+ # t.column :updated_at, :datetime
197
200
  # end
198
201
  #
199
- # Can also be written as follows using the short-hand:
202
+ # can also be written as follows using the short-hand:
200
203
  #
201
204
  # create_table :products do |t|
202
205
  # t.integer :shop_id, :creator_id
203
- # t.string :name, :value, :default => "Untitled"
206
+ # t.string :name, :value, default: "Untitled"
204
207
  # t.timestamps
205
208
  # end
206
209
  #
@@ -209,25 +212,32 @@ module ActiveRecord
209
212
  #
210
213
  # TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
211
214
  # column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
212
- # options, these will be used when creating the <tt>_type</tt> column. So what can be written like this:
215
+ # options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
216
+ # will also create an index, similar to calling <tt>add_index</tt>. So what can be written like this:
213
217
  #
214
218
  # create_table :taggings do |t|
215
219
  # t.integer :tag_id, :tagger_id, :taggable_id
216
220
  # t.string :tagger_type
217
- # t.string :taggable_type, :default => 'Photo'
221
+ # t.string :taggable_type, default: 'Photo'
218
222
  # end
223
+ # add_index :taggings, :tag_id, name: 'index_taggings_on_tag_id'
224
+ # add_index :taggings, [:tagger_id, :tagger_type]
219
225
  #
220
226
  # Can also be written as follows using references:
221
227
  #
222
228
  # create_table :taggings do |t|
223
- # t.references :tag
224
- # t.references :tagger, :polymorphic => true
225
- # t.references :taggable, :polymorphic => { :default => 'Photo' }
229
+ # t.references :tag, index: { name: 'index_taggings_on_tag_id' }
230
+ # t.references :tagger, polymorphic: true, index: true
231
+ # t.references :taggable, polymorphic: { default: 'Photo' }
226
232
  # end
227
233
  def column(name, type, options = {})
228
234
  name = name.to_s
229
235
  type = type.to_sym
230
236
 
237
+ if primary_key_column_name == name
238
+ raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
239
+ end
240
+
231
241
  column = self[name] || new_column_definition(@base, name, type)
232
242
 
233
243
  limit = options.fetch(:limit) do
@@ -242,21 +252,26 @@ module ActiveRecord
242
252
  self
243
253
  end
244
254
 
245
- %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
246
- class_eval <<-EOV, __FILE__, __LINE__ + 1
247
- def #{column_type}(*args) # def string(*args)
248
- options = args.extract_options! # options = args.extract_options!
249
- column_names = args # column_names = args
250
- type = :'#{column_type}' # type = :string
251
- column_names.each { |name| column(name, type, options) } # column_names.each { |name| column(name, type, options) }
252
- end # end
253
- EOV
255
+ [:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
256
+ define_method column_type do |*args|
257
+ options = args.extract_options!
258
+ column_names = args
259
+ column_names.each { |name| column(name, column_type, options) }
260
+ end
261
+ end
262
+
263
+ # Adds index options to the indexes hash, keyed by column name
264
+ # This is primarily used to track indexes that need to be created after the table
265
+ #
266
+ # index(:account_id, name: 'index_projects_on_account_id')
267
+ def index(column_name, options = {})
268
+ indexes[column_name] = options
254
269
  end
255
270
 
256
271
  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
257
272
  # <tt>:updated_at</tt> to the table.
258
273
  def timestamps(*args)
259
- options = { :null => false }.merge(args.extract_options!)
274
+ options = args.extract_options!
260
275
  column(:created_at, :datetime, options)
261
276
  column(:updated_at, :datetime, options)
262
277
  end
@@ -264,9 +279,11 @@ module ActiveRecord
264
279
  def references(*args)
265
280
  options = args.extract_options!
266
281
  polymorphic = options.delete(:polymorphic)
282
+ index_options = options.delete(:index)
267
283
  args.each do |col|
268
284
  column("#{col}_id", :integer, options)
269
- column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
285
+ column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
286
+ index(polymorphic ? %w(id type).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options
270
287
  end
271
288
  end
272
289
  alias :belongs_to :references
@@ -286,6 +303,11 @@ module ActiveRecord
286
303
  definition
287
304
  end
288
305
 
306
+ def primary_key_column_name
307
+ primary_key_column = columns.detect { |c| c.type == :primary_key }
308
+ primary_key_column && primary_key_column.name
309
+ end
310
+
289
311
  def native
290
312
  @base.native_database_types
291
313
  end
@@ -299,6 +321,7 @@ module ActiveRecord
299
321
  # change_table :table do |t|
300
322
  # t.column
301
323
  # t.index
324
+ # t.rename_index
302
325
  # t.timestamps
303
326
  # t.change
304
327
  # t.change_default
@@ -331,7 +354,7 @@ module ActiveRecord
331
354
 
332
355
  # Adds a new column to the named table.
333
356
  # See TableDefinition#column for details of the options you can use.
334
- # ===== Example
357
+ #
335
358
  # ====== Creating a simple column
336
359
  # t.column(:name, :string)
337
360
  def column(column_name, type, options = {})
@@ -346,13 +369,12 @@ module ActiveRecord
346
369
  # Adds a new index to the table. +column_name+ can be a single Symbol, or
347
370
  # an Array of Symbols. See SchemaStatements#add_index
348
371
  #
349
- # ===== Examples
350
372
  # ====== Creating a simple index
351
373
  # t.index(:name)
352
374
  # ====== Creating a unique index
353
- # t.index([:branch_id, :party_id], :unique => true)
375
+ # t.index([:branch_id, :party_id], unique: true)
354
376
  # ====== Creating a named index
355
- # t.index([:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
377
+ # t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
356
378
  def index(column_name, options = {})
357
379
  @base.add_index(@table_name, column_name, options)
358
380
  end
@@ -362,8 +384,15 @@ module ActiveRecord
362
384
  @base.index_exists?(@table_name, column_name, options)
363
385
  end
364
386
 
387
+ # Renames the given index on the table.
388
+ #
389
+ # t.rename_index(:user_id, :account_id)
390
+ def rename_index(index_name, new_index_name)
391
+ @base.rename_index(@table_name, index_name, new_index_name)
392
+ end
393
+
365
394
  # Adds timestamps (+created_at+ and +updated_at+) columns to the table. See SchemaStatements#add_timestamps
366
- # ===== Example
395
+ #
367
396
  # t.timestamps
368
397
  def timestamps
369
398
  @base.add_timestamps(@table_name)
@@ -371,15 +400,15 @@ module ActiveRecord
371
400
 
372
401
  # Changes the column's definition according to the new options.
373
402
  # See TableDefinition#column for details of the options you can use.
374
- # ===== Examples
375
- # t.change(:name, :string, :limit => 80)
403
+ #
404
+ # t.change(:name, :string, limit: 80)
376
405
  # t.change(:description, :text)
377
406
  def change(column_name, type, options = {})
378
407
  @base.change_column(@table_name, column_name, type, options)
379
408
  end
380
409
 
381
410
  # Sets a new default value for a column. See SchemaStatements#change_column_default
382
- # ===== Examples
411
+ #
383
412
  # t.change_default(:qualification, 'new')
384
413
  # t.change_default(:authorized, 1)
385
414
  def change_default(column_name, default)
@@ -387,37 +416,36 @@ module ActiveRecord
387
416
  end
388
417
 
389
418
  # Removes the column(s) from the table definition.
390
- # ===== Examples
419
+ #
391
420
  # t.remove(:qualification)
392
421
  # t.remove(:qualification, :experience)
393
422
  def remove(*column_names)
394
- @base.remove_column(@table_name, *column_names)
423
+ @base.remove_columns(@table_name, *column_names)
395
424
  end
396
425
 
397
426
  # Removes the given index from the table.
398
427
  #
399
- # ===== Examples
400
428
  # ====== Remove the index_table_name_on_column in the table_name table
401
429
  # t.remove_index :column
402
430
  # ====== Remove the index named index_table_name_on_branch_id in the table_name table
403
- # t.remove_index :column => :branch_id
431
+ # t.remove_index column: :branch_id
404
432
  # ====== Remove the index named index_table_name_on_branch_id_and_party_id in the table_name table
405
- # t.remove_index :column => [:branch_id, :party_id]
433
+ # t.remove_index column: [:branch_id, :party_id]
406
434
  # ====== Remove the index named by_branch_party in the table_name table
407
- # t.remove_index :name => :by_branch_party
435
+ # t.remove_index name: :by_branch_party
408
436
  def remove_index(options = {})
409
437
  @base.remove_index(@table_name, options)
410
438
  end
411
439
 
412
440
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
413
- # ===== Example
441
+ #
414
442
  # t.remove_timestamps
415
443
  def remove_timestamps
416
444
  @base.remove_timestamps(@table_name)
417
445
  end
418
446
 
419
447
  # Renames a column.
420
- # ===== Example
448
+ #
421
449
  # t.rename(:description, :name)
422
450
  def rename(column_name, new_column_name)
423
451
  @base.rename_column(@table_name, column_name, new_column_name)
@@ -425,61 +453,43 @@ module ActiveRecord
425
453
 
426
454
  # Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
427
455
  # <tt>references</tt> and <tt>belongs_to</tt> are acceptable.
428
- # ===== Examples
429
- # t.references(:goat)
430
- # t.references(:goat, :polymorphic => true)
431
- # t.belongs_to(:goat)
456
+ #
457
+ # t.references(:user)
458
+ # t.belongs_to(:supplier, polymorphic: true)
459
+ #
432
460
  def references(*args)
433
461
  options = args.extract_options!
434
- polymorphic = options.delete(:polymorphic)
435
- args.each do |col|
436
- @base.add_column(@table_name, "#{col}_id", :integer, options)
437
- @base.add_column(@table_name, "#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
462
+ args.each do |ref_name|
463
+ @base.add_reference(@table_name, ref_name, options)
438
464
  end
439
465
  end
440
466
  alias :belongs_to :references
441
467
 
442
468
  # Removes a reference. Optionally removes a +type+ column.
443
469
  # <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
444
- # ===== Examples
445
- # t.remove_references(:goat)
446
- # t.remove_references(:goat, :polymorphic => true)
447
- # t.remove_belongs_to(:goat)
470
+ #
471
+ # t.remove_references(:user)
472
+ # t.remove_belongs_to(:supplier, polymorphic: true)
473
+ #
448
474
  def remove_references(*args)
449
475
  options = args.extract_options!
450
- polymorphic = options.delete(:polymorphic)
451
- args.each do |col|
452
- @base.remove_column(@table_name, "#{col}_id")
453
- @base.remove_column(@table_name, "#{col}_type") unless polymorphic.nil?
476
+ args.each do |ref_name|
477
+ @base.remove_reference(@table_name, ref_name, options)
454
478
  end
455
479
  end
456
- alias :remove_belongs_to :remove_references
480
+ alias :remove_belongs_to :remove_references
457
481
 
458
482
  # Adds a column or columns of a specified type
459
- # ===== Examples
483
+ #
460
484
  # t.string(:goat)
461
485
  # t.string(:goat, :sheep)
462
- %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
463
- class_eval <<-EOV, __FILE__, __LINE__ + 1
464
- def #{column_type}(*args) # def string(*args)
465
- options = args.extract_options! # options = args.extract_options!
466
- column_names = args # column_names = args
467
- type = :'#{column_type}' # type = :string
468
- column_names.each do |name| # column_names.each do |name|
469
- column = ColumnDefinition.new(@base, name.to_s, type) # column = ColumnDefinition.new(@base, name, type)
470
- if options[:limit] # if options[:limit]
471
- column.limit = options[:limit] # column.limit = options[:limit]
472
- elsif native[type].is_a?(Hash) # elsif native[type].is_a?(Hash)
473
- column.limit = native[type][:limit] # column.limit = native[type][:limit]
474
- end # end
475
- column.precision = options[:precision] # column.precision = options[:precision]
476
- column.scale = options[:scale] # column.scale = options[:scale]
477
- column.default = options[:default] # column.default = options[:default]
478
- column.null = options[:null] # column.null = options[:null]
479
- @base.add_column(@table_name, name, column.sql_type, options) # @base.add_column(@table_name, name, column.sql_type, options)
480
- end # end
481
- end # end
482
- EOV
486
+ [:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
487
+ define_method column_type do |*args|
488
+ options = args.extract_options!
489
+ args.each do |name|
490
+ @base.add_column(@table_name, name, column_type, options)
491
+ end
492
+ end
483
493
  end
484
494
 
485
495
  private
@@ -0,0 +1,59 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters # :nodoc:
3
+ # The goal of this module is to move Adapter specific column
4
+ # definitions to the Adapter instead of having it in the schema
5
+ # dumper itself. This code represents the normal case.
6
+ # We can then redefine how certain data types may be handled in the schema dumper on the
7
+ # Adapter level by over-writing this code inside the database spececific adapters
8
+ module ColumnDumper
9
+ def column_spec(column, types)
10
+ spec = prepare_column_options(column, types)
11
+ (spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.to_s}: ")}
12
+ spec
13
+ end
14
+
15
+ # This can be overridden on a Adapter level basis to support other
16
+ # extended datatypes (Example: Adding an array option in the
17
+ # PostgreSQLAdapter)
18
+ def prepare_column_options(column, types)
19
+ spec = {}
20
+ spec[:name] = column.name.inspect
21
+
22
+ # AR has an optimization which handles zero-scale decimals as integers. This
23
+ # code ensures that the dumper still dumps the column as a decimal.
24
+ spec[:type] = if column.type == :integer && /^(numeric|decimal)/ =~ column.sql_type
25
+ 'decimal'
26
+ else
27
+ column.type.to_s
28
+ end
29
+ spec[:limit] = column.limit.inspect if column.limit != types[column.type][:limit] && spec[:type] != 'decimal'
30
+ spec[:precision] = column.precision.inspect if column.precision
31
+ spec[:scale] = column.scale.inspect if column.scale
32
+ spec[:null] = 'false' unless column.null
33
+ spec[:default] = default_string(column.default) if column.has_default?
34
+ spec
35
+ end
36
+
37
+ # Lists the valid migration options
38
+ def migration_keys
39
+ [:name, :limit, :precision, :scale, :default, :null]
40
+ end
41
+
42
+ private
43
+
44
+ def default_string(value)
45
+ case value
46
+ when BigDecimal
47
+ value.to_s
48
+ when Date, DateTime, Time
49
+ "'#{value.to_s(:db)}'"
50
+ when Range
51
+ # infinity dumps as Infinity, which causes uninitialized constant error
52
+ value.inspect.gsub('Infinity', '::Float::INFINITY')
53
+ else
54
+ value.inspect
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end