activerecord 4.0.0.beta1 → 4.0.0.rc1

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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +573 -30
  3. data/README.rdoc +3 -3
  4. data/lib/active_record.rb +8 -2
  5. data/lib/active_record/associations.rb +16 -9
  6. data/lib/active_record/associations/association.rb +8 -6
  7. data/lib/active_record/associations/association_scope.rb +2 -1
  8. data/lib/active_record/associations/belongs_to_association.rb +2 -2
  9. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  10. data/lib/active_record/associations/builder/belongs_to.rb +37 -5
  11. data/lib/active_record/associations/collection_association.rb +38 -14
  12. data/lib/active_record/associations/collection_proxy.rb +18 -15
  13. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +3 -3
  14. data/lib/active_record/associations/has_many_association.rb +4 -3
  15. data/lib/active_record/associations/has_many_through_association.rb +1 -1
  16. data/lib/active_record/associations/has_one_association.rb +1 -1
  17. data/lib/active_record/associations/join_dependency.rb +29 -8
  18. data/lib/active_record/associations/join_dependency/join_association.rb +26 -6
  19. data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
  20. data/lib/active_record/associations/join_dependency/join_part.rb +6 -6
  21. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +1 -1
  22. data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
  23. data/lib/active_record/associations/through_association.rb +1 -1
  24. data/lib/active_record/attribute_assignment.rb +5 -5
  25. data/lib/active_record/attribute_methods.rb +20 -5
  26. data/lib/active_record/attribute_methods/dirty.rb +5 -1
  27. data/lib/active_record/attribute_methods/primary_key.rb +1 -1
  28. data/lib/active_record/attribute_methods/serialization.rb +9 -2
  29. data/lib/active_record/autosave_association.rb +19 -5
  30. data/lib/active_record/base.rb +3 -3
  31. data/lib/active_record/callbacks.rb +1 -1
  32. data/lib/active_record/coders/yaml_column.rb +8 -13
  33. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +3 -9
  34. data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -1
  35. data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -1
  36. data/lib/active_record/connection_adapters/abstract/quoting.rb +2 -8
  37. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +60 -61
  38. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +13 -2
  39. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +291 -153
  40. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -1
  41. data/lib/active_record/connection_adapters/abstract_adapter.rb +92 -1
  42. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +55 -29
  43. data/lib/active_record/connection_adapters/column.rb +4 -4
  44. data/lib/active_record/connection_adapters/connection_specification.rb +2 -2
  45. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -3
  46. data/lib/active_record/connection_adapters/mysql_adapter.rb +5 -5
  47. data/lib/active_record/connection_adapters/postgresql/cast.rb +22 -2
  48. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -6
  49. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -13
  50. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +50 -9
  51. data/lib/active_record/connection_adapters/postgresql_adapter.rb +53 -24
  52. data/lib/active_record/connection_adapters/schema_cache.rb +35 -7
  53. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +13 -5
  54. data/lib/active_record/connection_handling.rb +7 -7
  55. data/lib/active_record/core.rb +43 -8
  56. data/lib/active_record/counter_cache.rb +2 -1
  57. data/lib/active_record/errors.rb +11 -10
  58. data/lib/active_record/explain.rb +9 -7
  59. data/lib/active_record/explain_registry.rb +30 -0
  60. data/lib/active_record/explain_subscriber.rb +3 -2
  61. data/lib/active_record/fixture_set/file.rb +1 -2
  62. data/lib/active_record/fixtures.rb +13 -7
  63. data/lib/active_record/inheritance.rb +12 -4
  64. data/lib/active_record/integration.rb +3 -3
  65. data/lib/active_record/locking/optimistic.rb +2 -2
  66. data/lib/active_record/log_subscriber.rb +2 -2
  67. data/lib/active_record/migration.rb +69 -21
  68. data/lib/active_record/model_schema.rb +1 -1
  69. data/lib/active_record/nested_attributes.rb +98 -46
  70. data/lib/active_record/persistence.rb +3 -3
  71. data/lib/active_record/querying.rb +1 -1
  72. data/lib/active_record/railtie.rb +18 -4
  73. data/lib/active_record/railties/console_sandbox.rb +3 -2
  74. data/lib/active_record/railties/controller_runtime.rb +2 -1
  75. data/lib/active_record/railties/databases.rake +38 -80
  76. data/lib/active_record/reflection.rb +36 -3
  77. data/lib/active_record/relation.rb +18 -8
  78. data/lib/active_record/relation/calculations.rb +10 -5
  79. data/lib/active_record/relation/delegation.rb +3 -5
  80. data/lib/active_record/relation/finder_methods.rb +27 -14
  81. data/lib/active_record/relation/merger.rb +30 -2
  82. data/lib/active_record/relation/predicate_builder.rb +1 -6
  83. data/lib/active_record/relation/query_methods.rb +113 -16
  84. data/lib/active_record/runtime_registry.rb +17 -0
  85. data/lib/active_record/schema_dumper.rb +5 -1
  86. data/lib/active_record/schema_migration.rb +8 -5
  87. data/lib/active_record/scoping.rb +56 -2
  88. data/lib/active_record/scoping/default.rb +12 -11
  89. data/lib/active_record/scoping/named.rb +7 -3
  90. data/lib/active_record/serialization.rb +1 -1
  91. data/lib/active_record/statement_cache.rb +26 -0
  92. data/lib/active_record/tasks/database_tasks.rb +55 -10
  93. data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
  94. data/lib/active_record/tasks/mysql_database_tasks.rb +7 -2
  95. data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
  96. data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
  97. data/lib/active_record/timestamp.rb +6 -0
  98. data/lib/active_record/transactions.rb +7 -3
  99. data/lib/active_record/validations.rb +1 -2
  100. data/lib/active_record/validations/uniqueness.rb +7 -3
  101. data/lib/active_record/version.rb +7 -6
  102. data/lib/rails/generators/active_record/migration/migration_generator.rb +9 -2
  103. data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
  104. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  105. data/lib/rails/generators/active_record/model/templates/model.rb +4 -1
  106. metadata +17 -12
  107. data/examples/associations.png +0 -0
@@ -107,7 +107,11 @@ module ActiveRecord
107
107
 
108
108
  def changes_from_zero_to_string?(old, value)
109
109
  # For columns with old 0 and value non-empty string
110
- old == 0 && value.is_a?(String) && value.present? && value != '0'
110
+ old == 0 && value.is_a?(String) && value.present? && non_zero?(value)
111
+ end
112
+
113
+ def non_zero?(value)
114
+ value !~ /\A0+(\.0+)?\z/
111
115
  end
112
116
  end
113
117
  end
@@ -90,7 +90,7 @@ module ActiveRecord
90
90
  base_name.foreign_key
91
91
  else
92
92
  if ActiveRecord::Base != self && table_exists?
93
- connection.schema_cache.primary_keys[table_name]
93
+ connection.schema_cache.primary_keys(table_name)
94
94
  else
95
95
  'id'
96
96
  end
@@ -11,6 +11,12 @@ module ActiveRecord
11
11
  end
12
12
 
13
13
  module ClassMethods
14
+ ##
15
+ # :method: serialized_attributes
16
+ #
17
+ # Returns a hash of all the attributes that have been specified for
18
+ # serialization as keys and their class restriction as values.
19
+
14
20
  # If you have an attribute that needs to be saved to the database as an
15
21
  # object, and retrieved as the same object, then specify the name of that
16
22
  # attribute using this method and it will be handled automatically. The
@@ -44,6 +50,7 @@ module ActiveRecord
44
50
  end
45
51
  end
46
52
 
53
+ # *DEPRECATED*: Use ActiveRecord::AttributeMethods::Serialization::ClassMethods#serialized_attributes class level method instead.
47
54
  def serialized_attributes
48
55
  message = "Instance level serialized_attributes method is deprecated, please use class level method."
49
56
  ActiveSupport::Deprecation.warn message
@@ -86,10 +93,10 @@ module ActiveRecord
86
93
 
87
94
  # This is only added to the model when serialize is called, which
88
95
  # ensures we do not make things slower when serialization is not used.
89
- module Behavior #:nodoc:
96
+ module Behavior # :nodoc:
90
97
  extend ActiveSupport::Concern
91
98
 
92
- module ClassMethods
99
+ module ClassMethods # :nodoc:
93
100
  def initialize_attributes(attributes, options = {})
94
101
  serialized = (options.delete(:serialized) { true }) ? :serialized : :unserialized
95
102
  super(attributes, options)
@@ -62,14 +62,14 @@ module ActiveRecord
62
62
  # Note that the model is _not_ yet removed from the database:
63
63
  #
64
64
  # id = post.author.id
65
- # Author.find_by_id(id).nil? # => false
65
+ # Author.find_by(id: id).nil? # => false
66
66
  #
67
67
  # post.save
68
68
  # post.reload.author # => nil
69
69
  #
70
70
  # Now it _is_ removed from the database:
71
71
  #
72
- # Author.find_by_id(id).nil? # => true
72
+ # Author.find_by(id: id).nil? # => true
73
73
  #
74
74
  # === One-to-many Example
75
75
  #
@@ -113,14 +113,14 @@ module ActiveRecord
113
113
  # Note that the model is _not_ yet removed from the database:
114
114
  #
115
115
  # id = post.comments.last.id
116
- # Comment.find_by_id(id).nil? # => false
116
+ # Comment.find_by(id: id).nil? # => false
117
117
  #
118
118
  # post.save
119
119
  # post.reload.comments.length # => 1
120
120
  #
121
121
  # Now it _is_ removed from the database:
122
122
  #
123
- # Comment.find_by_id(id).nil? # => true
123
+ # Comment.find_by(id: id).nil? # => true
124
124
 
125
125
  module AutosaveAssociation
126
126
  extend ActiveSupport::Concern
@@ -212,6 +212,7 @@ module ActiveRecord
212
212
  # Reloads the attributes of the object as usual and clears <tt>marked_for_destruction</tt> flag.
213
213
  def reload(options = nil)
214
214
  @marked_for_destruction = false
215
+ @destroyed_by_association = nil
215
216
  super
216
217
  end
217
218
 
@@ -231,6 +232,19 @@ module ActiveRecord
231
232
  @marked_for_destruction
232
233
  end
233
234
 
235
+ # Records the association that is being destroyed and destroying this
236
+ # record in the process.
237
+ def destroyed_by_association=(reflection)
238
+ @destroyed_by_association = reflection
239
+ end
240
+
241
+ # Returns the association for the parent being destroyed.
242
+ #
243
+ # Used to avoid updating the counter cache unnecessarily.
244
+ def destroyed_by_association
245
+ @destroyed_by_association
246
+ end
247
+
234
248
  # Returns whether or not this record has been changed in any way (including whether
235
249
  # any of its nested autosave associations are likewise changed)
236
250
  def changed_for_autosave?
@@ -347,7 +361,7 @@ module ActiveRecord
347
361
  end
348
362
 
349
363
  # reconstruct the scope now that we know the owner's id
350
- association.send(:reset_scope) if association.respond_to?(:reset_scope)
364
+ association.reset_scope if association.respond_to?(:reset_scope)
351
365
  end
352
366
  end
353
367
 
@@ -160,10 +160,10 @@ module ActiveRecord #:nodoc:
160
160
  #
161
161
  # == Dynamic attribute-based finders
162
162
  #
163
- # Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects
163
+ # Dynamic attribute-based finders are a mildly deprecated way of getting (and/or creating) objects
164
164
  # by simple queries without turning to SQL. They work by appending the name of an attribute
165
165
  # to <tt>find_by_</tt> like <tt>Person.find_by_user_name</tt>.
166
- # Instead of writing <tt>Person.where(user_name: user_name).first</tt>, you just do
166
+ # Instead of writing <tt>Person.find_by(user_name: user_name)</tt>, you can use
167
167
  # <tt>Person.find_by_user_name(user_name)</tt>.
168
168
  #
169
169
  # It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
@@ -172,7 +172,7 @@ module ActiveRecord #:nodoc:
172
172
  #
173
173
  # It's also possible to use multiple attributes in the same find by separating them with "_and_".
174
174
  #
175
- # Person.where(user_name: user_name, password: password).first
175
+ # Person.find_by(user_name: user_name, password: password)
176
176
  # Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
177
177
  #
178
178
  # It's even possible to call these dynamic finder methods on relations and named scopes.
@@ -83,7 +83,7 @@ module ActiveRecord
83
83
  #
84
84
  # In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+.
85
85
  # So, use the callback macros when you want to ensure that a certain callback is called for the entire
86
- # hierarchy, and use the regular overwriteable methods when you want to leave it up to each descendant
86
+ # hierarchy, and use the regular overwritable methods when you want to leave it up to each descendant
87
87
  # to decide whether they want to call +super+ and trigger the inherited callbacks.
88
88
  #
89
89
  # *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
@@ -3,7 +3,6 @@ require 'yaml'
3
3
  module ActiveRecord
4
4
  module Coders # :nodoc:
5
5
  class YAMLColumn # :nodoc:
6
- RESCUE_ERRORS = [ ArgumentError, Psych::SyntaxError ]
7
6
 
8
7
  attr_accessor :object_class
9
8
 
@@ -24,19 +23,15 @@ module ActiveRecord
24
23
  def load(yaml)
25
24
  return object_class.new if object_class != Object && yaml.nil?
26
25
  return yaml unless yaml.is_a?(String) && yaml =~ /^---/
27
- begin
28
- obj = YAML.load(yaml)
29
-
30
- unless obj.is_a?(object_class) || obj.nil?
31
- raise SerializationTypeMismatch,
32
- "Attribute was supposed to be a #{object_class}, but was a #{obj.class}"
33
- end
34
- obj ||= object_class.new if object_class != Object
35
-
36
- obj
37
- rescue *RESCUE_ERRORS
38
- yaml
26
+ obj = YAML.load(yaml)
27
+
28
+ unless obj.is_a?(object_class) || obj.nil?
29
+ raise SerializationTypeMismatch,
30
+ "Attribute was supposed to be a #{object_class}, but was a #{obj.class}"
39
31
  end
32
+ obj ||= object_class.new if object_class != Object
33
+
34
+ obj
40
35
  end
41
36
  end
42
37
  end
@@ -253,14 +253,6 @@ module ActiveRecord
253
253
  @available = Queue.new self
254
254
  end
255
255
 
256
- # Hack for tests to be able to add connections. Do not call outside of tests
257
- def insert_connection_for_test!(c) #:nodoc:
258
- synchronize do
259
- @connections << c
260
- @available.add c
261
- end
262
- end
263
-
264
256
  # Retrieve the connection associated with the current thread, or call
265
257
  # #checkout to obtain one if necessary.
266
258
  #
@@ -406,7 +398,9 @@ module ActiveRecord
406
398
  synchronize do
407
399
  stale = Time.now - @dead_connection_timeout
408
400
  connections.dup.each do |conn|
409
- remove conn if conn.in_use? && stale > conn.last_use && !conn.active?
401
+ if conn.in_use? && stale > conn.last_use && !conn.active?
402
+ remove conn
403
+ end
410
404
  end
411
405
  end
412
406
  end
@@ -21,7 +21,7 @@ module ActiveRecord
21
21
  # limit is enforced by rails and Is less than or equal to
22
22
  # <tt>index_name_length</tt>. The gap between
23
23
  # <tt>index_name_length</tt> is to allow internal rails
24
- # opreations to use prefixes in temporary opreations.
24
+ # operations to use prefixes in temporary operations.
25
25
  def allowed_index_name_length
26
26
  index_name_length
27
27
  end
@@ -125,7 +125,8 @@ module ActiveRecord
125
125
  # In order to get around this problem, #transaction will emulate the effect
126
126
  # of nested transactions, by using savepoints:
127
127
  # http://dev.mysql.com/doc/refman/5.0/en/savepoint.html
128
- # Savepoints are supported by MySQL and PostgreSQL, but not SQLite3.
128
+ # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
129
+ # supports savepoints.
129
130
  #
130
131
  # It is safe to call this method if a database transaction is already open,
131
132
  # i.e. if #transaction is called within another #transaction block. In case
@@ -25,19 +25,13 @@ module ActiveRecord
25
25
  when true, false
26
26
  if column && column.type == :integer
27
27
  value ? '1' : '0'
28
- elsif column && [:text, :string, :binary].include?(column.type)
29
- value ? "'1'" : "'0'"
30
28
  else
31
29
  value ? quoted_true : quoted_false
32
30
  end
33
31
  # BigDecimals need to be put in a non-normalized form and quoted.
34
32
  when nil then "NULL"
35
- when Numeric, ActiveSupport::Duration
36
- value = BigDecimal === value ? value.to_s('F') : value.to_s
37
- if column && ![:integer, :float, :decimal].include?(column.type)
38
- value = "'#{value}'"
39
- end
40
- value
33
+ when BigDecimal then value.to_s('F')
34
+ when Numeric, ActiveSupport::Duration then value.to_s
41
35
  when Date, Time then "'#{quoted_date(value)}'"
42
36
  when Symbol then "'#{quote_string(value.to_s)}'"
43
37
  when Class then "'#{value.to_s}'"
@@ -8,44 +8,28 @@ module ActiveRecord
8
8
  # Abstract representation of an index definition on a table. Instances of
9
9
  # this type are typically created and returned by methods in database
10
10
  # adapters. e.g. ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#indexes
11
- class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where) #:nodoc:
11
+ class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using) #:nodoc:
12
12
  end
13
13
 
14
14
  # Abstract representation of a column definition. Instances of this type
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(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc:
19
-
18
+ class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key) #:nodoc:
20
19
  def string_to_binary(value)
21
20
  value
22
21
  end
23
22
 
24
- def sql_type
25
- base.type_to_sql(type.to_sym, limit, precision, scale)
26
- end
27
-
28
- def to_sql
29
- column_sql = "#{base.quote_column_name(name)} #{sql_type}"
30
- column_options = {}
31
- column_options[:null] = null unless null.nil?
32
- column_options[:default] = default unless default.nil?
33
- add_column_options!(column_sql, column_options) unless type.to_sym == :primary_key
34
- column_sql
23
+ def primary_key?
24
+ primary_key || type.to_sym == :primary_key
35
25
  end
36
-
37
- private
38
-
39
- def add_column_options!(sql, options)
40
- base.add_column_options!(sql, options.merge(:column => self))
41
- end
42
26
  end
43
27
 
44
28
  # Represents the schema of an SQL table in an abstract way. This class
45
29
  # provides methods for manipulating the schema representation.
46
30
  #
47
- # Inside migration files, the +t+ object in +create_table+ and
48
- # +change_table+ is actually of this type:
31
+ # Inside migration files, the +t+ object in +create_table+
32
+ # is actually of this type:
49
33
  #
50
34
  # class SomeMigration < ActiveRecord::Migration
51
35
  # def up
@@ -64,28 +48,25 @@ module ActiveRecord
64
48
  class TableDefinition
65
49
  # An array of ColumnDefinition objects, representing the column changes
66
50
  # that have been defined.
67
- attr_accessor :columns, :indexes
51
+ attr_accessor :indexes
52
+ attr_reader :name, :temporary, :options
68
53
 
69
- def initialize(base)
70
- @columns = []
54
+ def initialize(types, name, temporary, options)
71
55
  @columns_hash = {}
72
56
  @indexes = {}
73
- @base = base
57
+ @native = types
58
+ @temporary = temporary
59
+ @options = options
60
+ @name = name
74
61
  end
75
62
 
76
- def xml(*args)
77
- raise NotImplementedError unless %w{
78
- sqlite mysql mysql2
79
- }.include? @base.adapter_name.downcase
80
-
81
- options = args.extract_options!
82
- column(args[0], :text, options)
83
- end
63
+ def columns; @columns_hash.values; end
84
64
 
85
65
  # Appends a primary key definition to the table definition.
86
66
  # Can be called multiple times, but this is probably not a good idea.
87
- def primary_key(name)
88
- column(name, :primary_key)
67
+ def primary_key(name, type = :primary_key, options = {})
68
+ options[:primary_key] = true
69
+ column(name, type, options)
89
70
  end
90
71
 
91
72
  # Returns a ColumnDefinition for the column with name +name+.
@@ -238,20 +219,14 @@ module ActiveRecord
238
219
  raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
239
220
  end
240
221
 
241
- column = self[name] || new_column_definition(@base, name, type)
242
-
243
- limit = options.fetch(:limit) do
244
- native[type][:limit] if native[type].is_a?(Hash)
245
- end
246
-
247
- column.limit = limit
248
- column.precision = options[:precision]
249
- column.scale = options[:scale]
250
- column.default = options[:default]
251
- column.null = options[:null]
222
+ @columns_hash[name] = new_column_definition(name, type, options)
252
223
  self
253
224
  end
254
225
 
226
+ def remove_column(name)
227
+ @columns_hash.delete name.to_s
228
+ end
229
+
255
230
  [:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
256
231
  define_method column_type do |*args|
257
232
  options = args.extract_options!
@@ -283,33 +258,57 @@ module ActiveRecord
283
258
  args.each do |col|
284
259
  column("#{col}_id", :integer, options)
285
260
  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
261
+ index(polymorphic ? %w(id type).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
287
262
  end
288
263
  end
289
264
  alias :belongs_to :references
290
265
 
291
- # Returns a String whose contents are the column definitions
292
- # concatenated together. This string can then be prepended and appended to
293
- # to generate the final SQL to create the table.
294
- def to_sql
295
- @columns.map { |c| c.to_sql } * ', '
266
+ def new_column_definition(name, type, options) # :nodoc:
267
+ column = create_column_definition name, type
268
+ limit = options.fetch(:limit) do
269
+ native[type][:limit] if native[type].is_a?(Hash)
270
+ end
271
+
272
+ column.limit = limit
273
+ column.precision = options[:precision]
274
+ column.scale = options[:scale]
275
+ column.default = options[:default]
276
+ column.null = options[:null]
277
+ column.first = options[:first]
278
+ column.after = options[:after]
279
+ column.primary_key = type == :primary_key || options[:primary_key]
280
+ column
296
281
  end
297
282
 
298
283
  private
299
- def new_column_definition(base, name, type)
300
- definition = ColumnDefinition.new base, name, type
301
- @columns << definition
302
- @columns_hash[name] = definition
303
- definition
284
+ def create_column_definition(name, type)
285
+ ColumnDefinition.new name, type
304
286
  end
305
287
 
306
288
  def primary_key_column_name
307
- primary_key_column = columns.detect { |c| c.type == :primary_key }
289
+ primary_key_column = columns.detect { |c| c.primary_key? }
308
290
  primary_key_column && primary_key_column.name
309
291
  end
310
292
 
311
293
  def native
312
- @base.native_database_types
294
+ @native
295
+ end
296
+ end
297
+
298
+ class AlterTable # :nodoc:
299
+ attr_reader :adds
300
+
301
+ def initialize(td)
302
+ @td = td
303
+ @adds = []
304
+ end
305
+
306
+ def name; @td.name; end
307
+
308
+ def add_column(name, type, options)
309
+ name = name.to_s
310
+ type = type.to_sym
311
+ @adds << @td.new_column_definition(name, type, options)
313
312
  end
314
313
  end
315
314
 
@@ -489,7 +488,7 @@ module ActiveRecord
489
488
  args.each do |name|
490
489
  @base.add_column(@table_name, name, column_type, options)
491
490
  end
492
- end
491
+ end
493
492
  end
494
493
 
495
494
  private