activerecord 4.1.15 → 4.2.11.3

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 +5 -5
  2. data/CHANGELOG.md +1162 -1792
  3. data/README.rdoc +15 -10
  4. data/lib/active_record.rb +4 -0
  5. data/lib/active_record/aggregations.rb +15 -8
  6. data/lib/active_record/association_relation.rb +13 -0
  7. data/lib/active_record/associations.rb +158 -49
  8. data/lib/active_record/associations/alias_tracker.rb +3 -12
  9. data/lib/active_record/associations/association.rb +16 -4
  10. data/lib/active_record/associations/association_scope.rb +83 -38
  11. data/lib/active_record/associations/belongs_to_association.rb +28 -10
  12. data/lib/active_record/associations/builder/association.rb +15 -4
  13. data/lib/active_record/associations/builder/belongs_to.rb +7 -29
  14. data/lib/active_record/associations/builder/collection_association.rb +5 -1
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +8 -13
  16. data/lib/active_record/associations/builder/has_many.rb +1 -1
  17. data/lib/active_record/associations/builder/has_one.rb +2 -2
  18. data/lib/active_record/associations/builder/singular_association.rb +8 -1
  19. data/lib/active_record/associations/collection_association.rb +63 -27
  20. data/lib/active_record/associations/collection_proxy.rb +29 -35
  21. data/lib/active_record/associations/foreign_association.rb +11 -0
  22. data/lib/active_record/associations/has_many_association.rb +83 -22
  23. data/lib/active_record/associations/has_many_through_association.rb +49 -26
  24. data/lib/active_record/associations/has_one_association.rb +1 -1
  25. data/lib/active_record/associations/join_dependency.rb +26 -13
  26. data/lib/active_record/associations/join_dependency/join_association.rb +25 -15
  27. data/lib/active_record/associations/join_dependency/join_part.rb +0 -1
  28. data/lib/active_record/associations/preloader.rb +36 -26
  29. data/lib/active_record/associations/preloader/association.rb +14 -11
  30. data/lib/active_record/associations/preloader/through_association.rb +4 -3
  31. data/lib/active_record/associations/singular_association.rb +17 -2
  32. data/lib/active_record/associations/through_association.rb +5 -12
  33. data/lib/active_record/attribute.rb +163 -0
  34. data/lib/active_record/attribute_assignment.rb +19 -11
  35. data/lib/active_record/attribute_decorators.rb +66 -0
  36. data/lib/active_record/attribute_methods.rb +56 -94
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
  38. data/lib/active_record/attribute_methods/dirty.rb +107 -43
  39. data/lib/active_record/attribute_methods/primary_key.rb +7 -8
  40. data/lib/active_record/attribute_methods/query.rb +1 -1
  41. data/lib/active_record/attribute_methods/read.rb +22 -59
  42. data/lib/active_record/attribute_methods/serialization.rb +16 -150
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -40
  44. data/lib/active_record/attribute_methods/write.rb +9 -24
  45. data/lib/active_record/attribute_set.rb +81 -0
  46. data/lib/active_record/attribute_set/builder.rb +106 -0
  47. data/lib/active_record/attributes.rb +147 -0
  48. data/lib/active_record/autosave_association.rb +19 -12
  49. data/lib/active_record/base.rb +13 -24
  50. data/lib/active_record/callbacks.rb +6 -6
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +84 -52
  52. data/lib/active_record/connection_adapters/abstract/database_statements.rb +52 -50
  53. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  54. data/lib/active_record/connection_adapters/abstract/quoting.rb +60 -60
  55. data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
  56. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +39 -4
  57. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +138 -56
  58. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -34
  59. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +268 -71
  60. data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -118
  61. data/lib/active_record/connection_adapters/abstract_adapter.rb +171 -59
  62. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +293 -139
  63. data/lib/active_record/connection_adapters/column.rb +29 -240
  64. data/lib/active_record/connection_adapters/connection_specification.rb +15 -24
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -32
  66. data/lib/active_record/connection_adapters/mysql_adapter.rb +67 -144
  67. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
  68. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  69. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -25
  70. data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -388
  71. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  73. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  78. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  79. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  80. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  96. data/lib/active_record/connection_adapters/postgresql/quoting.rb +46 -136
  97. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  99. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +131 -43
  100. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  101. data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -477
  102. data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
  103. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -75
  104. data/lib/active_record/connection_handling.rb +1 -1
  105. data/lib/active_record/core.rb +163 -39
  106. data/lib/active_record/counter_cache.rb +60 -6
  107. data/lib/active_record/enum.rb +9 -11
  108. data/lib/active_record/errors.rb +53 -30
  109. data/lib/active_record/explain.rb +1 -1
  110. data/lib/active_record/explain_subscriber.rb +1 -1
  111. data/lib/active_record/fixtures.rb +55 -69
  112. data/lib/active_record/gem_version.rb +4 -4
  113. data/lib/active_record/inheritance.rb +35 -10
  114. data/lib/active_record/integration.rb +4 -4
  115. data/lib/active_record/legacy_yaml_adapter.rb +30 -0
  116. data/lib/active_record/locking/optimistic.rb +46 -26
  117. data/lib/active_record/migration.rb +71 -46
  118. data/lib/active_record/migration/command_recorder.rb +19 -2
  119. data/lib/active_record/migration/join_table.rb +1 -1
  120. data/lib/active_record/model_schema.rb +52 -58
  121. data/lib/active_record/nested_attributes.rb +5 -5
  122. data/lib/active_record/no_touching.rb +1 -1
  123. data/lib/active_record/persistence.rb +46 -26
  124. data/lib/active_record/query_cache.rb +3 -3
  125. data/lib/active_record/querying.rb +10 -7
  126. data/lib/active_record/railtie.rb +18 -11
  127. data/lib/active_record/railties/databases.rake +50 -51
  128. data/lib/active_record/readonly_attributes.rb +0 -1
  129. data/lib/active_record/reflection.rb +273 -114
  130. data/lib/active_record/relation.rb +57 -25
  131. data/lib/active_record/relation/batches.rb +0 -2
  132. data/lib/active_record/relation/calculations.rb +41 -37
  133. data/lib/active_record/relation/finder_methods.rb +70 -47
  134. data/lib/active_record/relation/merger.rb +39 -29
  135. data/lib/active_record/relation/predicate_builder.rb +16 -8
  136. data/lib/active_record/relation/predicate_builder/array_handler.rb +32 -13
  137. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -5
  138. data/lib/active_record/relation/query_methods.rb +114 -65
  139. data/lib/active_record/relation/spawn_methods.rb +3 -0
  140. data/lib/active_record/result.rb +18 -7
  141. data/lib/active_record/sanitization.rb +12 -2
  142. data/lib/active_record/schema.rb +0 -1
  143. data/lib/active_record/schema_dumper.rb +59 -28
  144. data/lib/active_record/schema_migration.rb +5 -4
  145. data/lib/active_record/scoping/default.rb +6 -4
  146. data/lib/active_record/scoping/named.rb +4 -0
  147. data/lib/active_record/serializers/xml_serializer.rb +3 -7
  148. data/lib/active_record/statement_cache.rb +95 -10
  149. data/lib/active_record/store.rb +5 -5
  150. data/lib/active_record/tasks/database_tasks.rb +61 -6
  151. data/lib/active_record/tasks/mysql_database_tasks.rb +32 -17
  152. data/lib/active_record/tasks/postgresql_database_tasks.rb +20 -9
  153. data/lib/active_record/timestamp.rb +9 -7
  154. data/lib/active_record/transactions.rb +53 -27
  155. data/lib/active_record/type.rb +23 -0
  156. data/lib/active_record/type/big_integer.rb +13 -0
  157. data/lib/active_record/type/binary.rb +50 -0
  158. data/lib/active_record/type/boolean.rb +31 -0
  159. data/lib/active_record/type/date.rb +50 -0
  160. data/lib/active_record/type/date_time.rb +54 -0
  161. data/lib/active_record/type/decimal.rb +64 -0
  162. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  163. data/lib/active_record/type/decorator.rb +14 -0
  164. data/lib/active_record/type/float.rb +19 -0
  165. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  166. data/lib/active_record/type/integer.rb +59 -0
  167. data/lib/active_record/type/mutable.rb +16 -0
  168. data/lib/active_record/type/numeric.rb +36 -0
  169. data/lib/active_record/type/serialized.rb +62 -0
  170. data/lib/active_record/type/string.rb +40 -0
  171. data/lib/active_record/type/text.rb +11 -0
  172. data/lib/active_record/type/time.rb +26 -0
  173. data/lib/active_record/type/time_value.rb +38 -0
  174. data/lib/active_record/type/type_map.rb +64 -0
  175. data/lib/active_record/type/unsigned_integer.rb +15 -0
  176. data/lib/active_record/type/value.rb +110 -0
  177. data/lib/active_record/validations.rb +25 -19
  178. data/lib/active_record/validations/associated.rb +5 -3
  179. data/lib/active_record/validations/presence.rb +5 -3
  180. data/lib/active_record/validations/uniqueness.rb +25 -29
  181. data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
  182. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
  183. data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
  184. metadata +66 -11
  185. data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -1,14 +1,14 @@
1
1
  module ActiveRecord
2
- # Returns the version of the currently loaded ActiveRecord as a <tt>Gem::Version</tt>
2
+ # Returns the version of the currently loaded Active Record as a <tt>Gem::Version</tt>
3
3
  def self.gem_version
4
4
  Gem::Version.new VERSION::STRING
5
5
  end
6
6
 
7
7
  module VERSION
8
8
  MAJOR = 4
9
- MINOR = 1
10
- TINY = 15
11
- PRE = nil
9
+ MINOR = 2
10
+ TINY = 11
11
+ PRE = "3"
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
14
  end
@@ -1,6 +1,37 @@
1
1
  require 'active_support/core_ext/hash/indifferent_access'
2
2
 
3
3
  module ActiveRecord
4
+ # == Single table inheritance
5
+ #
6
+ # Active Record allows inheritance by storing the name of the class in a column that by
7
+ # default is named "type" (can be changed by overwriting <tt>Base.inheritance_column</tt>).
8
+ # This means that an inheritance looking like this:
9
+ #
10
+ # class Company < ActiveRecord::Base; end
11
+ # class Firm < Company; end
12
+ # class Client < Company; end
13
+ # class PriorityClient < Client; end
14
+ #
15
+ # When you do <tt>Firm.create(name: "37signals")</tt>, this record will be saved in
16
+ # the companies table with type = "Firm". You can then fetch this row again using
17
+ # <tt>Company.where(name: '37signals').first</tt> and it will return a Firm object.
18
+ #
19
+ # Be aware that because the type column is an attribute on the record every new
20
+ # subclass will instantly be marked as dirty and the type column will be included
21
+ # in the list of changed attributes on the record. This is different from non
22
+ # STI classes:
23
+ #
24
+ # Company.new.changed? # => false
25
+ # Firm.new.changed? # => true
26
+ # Firm.new.changes # => {"type"=>["","Firm"]}
27
+ #
28
+ # If you don't have a type column defined in your table, single-table inheritance won't
29
+ # be triggered. In that case, it'll work just like normal subclasses with no special magic
30
+ # for differentiating between them or reloading the right type with find.
31
+ #
32
+ # Note, all the attributes for all the cases are kept in the same table. Read more:
33
+ # http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
34
+ #
4
35
  module Inheritance
5
36
  extend ActiveSupport::Concern
6
37
 
@@ -49,12 +80,12 @@ module ActiveRecord
49
80
  end
50
81
 
51
82
  def symbolized_base_class
52
- ActiveSupport::Deprecation.warn("ActiveRecord::Base.symbolized_base_class is deprecated and will be removed without replacement.")
83
+ ActiveSupport::Deprecation.warn('`ActiveRecord::Base.symbolized_base_class` is deprecated and will be removed without replacement.')
53
84
  @symbolized_base_class ||= base_class.to_s.to_sym
54
85
  end
55
86
 
56
87
  def symbolized_sti_name
57
- ActiveSupport::Deprecation.warn("ActiveRecord::Base.symbolized_sti_name is deprecated and will be removed without replacement.")
88
+ ActiveSupport::Deprecation.warn('`ActiveRecord::Base.symbolized_sti_name` is deprecated and will be removed without replacement.')
58
89
  @symbolized_sti_name ||= sti_name.present? ? sti_name.to_sym : symbolized_base_class
59
90
  end
60
91
 
@@ -120,14 +151,8 @@ module ActiveRecord
120
151
  candidates << type_name
121
152
 
122
153
  candidates.each do |candidate|
123
- begin
124
- constant = ActiveSupport::Dependencies.constantize(candidate)
125
- return constant if candidate == constant.to_s
126
- # We don't want to swallow NoMethodError < NameError errors
127
- rescue NoMethodError
128
- raise
129
- rescue NameError
130
- end
154
+ constant = ActiveSupport::Dependencies.safe_constantize(candidate)
155
+ return constant if candidate == constant.to_s
131
156
  end
132
157
 
133
158
  raise NameError.new("uninitialized constant #{candidates.first}", candidates.first)
@@ -55,16 +55,16 @@ module ActiveRecord
55
55
  def cache_key(*timestamp_names)
56
56
  case
57
57
  when new_record?
58
- "#{self.class.model_name.cache_key}/new"
58
+ "#{model_name.cache_key}/new"
59
59
  when timestamp_names.any?
60
60
  timestamp = max_updated_column_timestamp(timestamp_names)
61
61
  timestamp = timestamp.utc.to_s(cache_timestamp_format)
62
- "#{self.class.model_name.cache_key}/#{id}-#{timestamp}"
62
+ "#{model_name.cache_key}/#{id}-#{timestamp}"
63
63
  when timestamp = max_updated_column_timestamp
64
64
  timestamp = timestamp.utc.to_s(cache_timestamp_format)
65
- "#{self.class.model_name.cache_key}/#{id}-#{timestamp}"
65
+ "#{model_name.cache_key}/#{id}-#{timestamp}"
66
66
  else
67
- "#{self.class.model_name.cache_key}/#{id}"
67
+ "#{model_name.cache_key}/#{id}"
68
68
  end
69
69
  end
70
70
 
@@ -0,0 +1,30 @@
1
+ module ActiveRecord
2
+ module LegacyYamlAdapter
3
+ def self.convert(klass, coder)
4
+ return coder unless coder.is_a?(Psych::Coder)
5
+
6
+ case coder["active_record_yaml_version"]
7
+ when 0 then coder
8
+ else
9
+ if coder["attributes"].is_a?(AttributeSet)
10
+ coder
11
+ else
12
+ Rails41.convert(klass, coder)
13
+ end
14
+ end
15
+ end
16
+
17
+ module Rails41
18
+ def self.convert(klass, coder)
19
+ attributes = klass.attributes_builder
20
+ .build_from_database(coder["attributes"])
21
+ new_record = coder["attributes"][klass.primary_key].blank?
22
+
23
+ {
24
+ "attributes" => attributes,
25
+ "new_record" => new_record,
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -66,7 +66,16 @@ module ActiveRecord
66
66
  send(lock_col + '=', previous_lock_value + 1)
67
67
  end
68
68
 
69
- def _update_record(attribute_names = @attributes.keys) #:nodoc:
69
+ def _create_record(attribute_names = self.attribute_names, *) # :nodoc:
70
+ if locking_enabled?
71
+ # We always want to persist the locking version, even if we don't detect
72
+ # a change from the default, since the database might have no default
73
+ attribute_names |= [self.class.locking_column]
74
+ end
75
+ super
76
+ end
77
+
78
+ def _update_record(attribute_names = self.attribute_names) #:nodoc:
70
79
  return super unless locking_enabled?
71
80
  return 0 if attribute_names.empty?
72
81
 
@@ -80,17 +89,15 @@ module ActiveRecord
80
89
  begin
81
90
  relation = self.class.unscoped
82
91
 
83
- stmt = relation.where(
84
- relation.table[self.class.primary_key].eq(id).and(
85
- relation.table[lock_col].eq(self.class.quote_value(previous_lock_value, column_for_attribute(lock_col)))
86
- )
87
- ).arel.compile_update(
88
- arel_attributes_with_values_for_update(attribute_names),
89
- self.class.primary_key
92
+ affected_rows = relation.where(
93
+ self.class.primary_key => id,
94
+ lock_col => previous_lock_value,
95
+ ).update_all(
96
+ Hash[attributes_for_update(attribute_names).map do |name|
97
+ [name, _read_attribute(name)]
98
+ end]
90
99
  )
91
100
 
92
- affected_rows = self.class.connection.update stmt
93
-
94
101
  unless affected_rows == 1
95
102
  raise ActiveRecord::StaleObjectError.new(self, "update")
96
103
  end
@@ -120,7 +127,7 @@ module ActiveRecord
120
127
  if locking_enabled?
121
128
  column_name = self.class.locking_column
122
129
  column = self.class.columns_hash[column_name]
123
- substitute = self.class.connection.substitute_at(column, relation.bind_values.length)
130
+ substitute = self.class.connection.substitute_at(column)
124
131
 
125
132
  relation = relation.where(self.class.arel_table[column_name].eq(substitute))
126
133
  relation.bind_values << [column, self[column_name].to_i]
@@ -141,7 +148,7 @@ module ActiveRecord
141
148
 
142
149
  # Set the column to use for optimistic locking. Defaults to +lock_version+.
143
150
  def locking_column=(value)
144
- @column_defaults = nil
151
+ clear_caches_calculated_from_columns
145
152
  @locking_column = value.to_s
146
153
  end
147
154
 
@@ -151,12 +158,6 @@ module ActiveRecord
151
158
  @locking_column
152
159
  end
153
160
 
154
- # Quote the column name used for optimistic locking.
155
- def quoted_locking_column
156
- ActiveSupport::Deprecation.warn "ActiveRecord::Base.quoted_locking_column is deprecated and will be removed in Rails 4.2 or later."
157
- connection.quote_column_name(locking_column)
158
- end
159
-
160
161
  # Reset the column used for optimistic locking back to the +lock_version+ default.
161
162
  def reset_locking_column
162
163
  self.locking_column = DEFAULT_LOCKING_COLUMN
@@ -169,18 +170,37 @@ module ActiveRecord
169
170
  super
170
171
  end
171
172
 
172
- def column_defaults
173
- @column_defaults ||= begin
174
- defaults = super
175
-
176
- if defaults.key?(locking_column) && lock_optimistically
177
- defaults[locking_column] ||= 0
173
+ private
174
+
175
+ # We need to apply this decorator here, rather than on module inclusion. The closure
176
+ # created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the
177
+ # sub class being decorated. As such, changes to `lock_optimistically`, or
178
+ # `locking_column` would not be picked up.
179
+ def inherited(subclass)
180
+ subclass.class_eval do
181
+ is_lock_column = ->(name, _) { lock_optimistically && name == locking_column }
182
+ decorate_matching_attribute_types(is_lock_column, :_optimistic_locking) do |type|
183
+ LockingType.new(type)
178
184
  end
179
-
180
- defaults
181
185
  end
186
+ super
182
187
  end
183
188
  end
184
189
  end
190
+
191
+ class LockingType < SimpleDelegator # :nodoc:
192
+ def type_cast_from_database(value)
193
+ # `nil` *should* be changed to 0
194
+ super.to_i
195
+ end
196
+
197
+ def init_with(coder)
198
+ __setobj__(coder['subtype'])
199
+ end
200
+
201
+ def encode_with(coder)
202
+ coder['subtype'] = __getobj__
203
+ end
204
+ end
185
205
  end
186
206
  end
@@ -39,7 +39,7 @@ module ActiveRecord
39
39
 
40
40
  class PendingMigrationError < MigrationError#:nodoc:
41
41
  def initialize
42
- if defined?(Rails)
42
+ if defined?(Rails.env)
43
43
  super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate RAILS_ENV=#{::Rails.env}")
44
44
  else
45
45
  super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate")
@@ -161,21 +161,14 @@ module ActiveRecord
161
161
  # in the <tt>db/migrate/</tt> directory where <tt>timestamp</tt> is the
162
162
  # UTC formatted date and time that the migration was generated.
163
163
  #
164
- # You may then edit the <tt>up</tt> and <tt>down</tt> methods of
165
- # MyNewMigration.
166
- #
167
164
  # There is a special syntactic shortcut to generate migrations that add fields to a table.
168
165
  #
169
166
  # rails generate migration add_fieldname_to_tablename fieldname:string
170
167
  #
171
168
  # This will generate the file <tt>timestamp_add_fieldname_to_tablename</tt>, which will look like this:
172
169
  # class AddFieldnameToTablename < ActiveRecord::Migration
173
- # def up
174
- # add_column :tablenames, :fieldname, :string
175
- # end
176
- #
177
- # def down
178
- # remove_column :tablenames, :fieldname
170
+ # def change
171
+ # add_column :tablenames, :field, :string
179
172
  # end
180
173
  # end
181
174
  #
@@ -188,14 +181,17 @@ module ActiveRecord
188
181
  #
189
182
  # To roll the database back to a previous migration version, use
190
183
  # <tt>rake db:migrate VERSION=X</tt> where <tt>X</tt> is the version to which
191
- # you wish to downgrade. If any of the migrations throw an
192
- # <tt>ActiveRecord::IrreversibleMigration</tt> exception, that step will fail and you'll
193
- # have some manual work to do.
184
+ # you wish to downgrade. Alternatively, you can also use the STEP option if you
185
+ # wish to rollback last few migrations. <tt>rake db:migrate STEP=2</tt> will rollback
186
+ # the latest two migrations.
187
+ #
188
+ # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
189
+ # that step will fail and you'll have some manual work to do.
194
190
  #
195
191
  # == Database support
196
192
  #
197
193
  # Migrations are currently supported in MySQL, PostgreSQL, SQLite,
198
- # SQL Server, Sybase, and Oracle (all supported databases except DB2).
194
+ # SQL Server, and Oracle (all supported databases except DB2).
199
195
  #
200
196
  # == More examples
201
197
  #
@@ -311,9 +307,8 @@ module ActiveRecord
311
307
  #
312
308
  # == Reversible Migrations
313
309
  #
314
- # Starting with Rails 3.1, you will be able to define reversible migrations.
315
310
  # Reversible migrations are migrations that know how to go +down+ for you.
316
- # You simply supply the +up+ logic, and the Migration system will figure out
311
+ # You simply supply the +up+ logic, and the Migration system figures out
317
312
  # how to execute the down commands for you.
318
313
  #
319
314
  # To define a reversible migration, define the +change+ method in your
@@ -372,13 +367,21 @@ module ActiveRecord
372
367
  end
373
368
 
374
369
  def call(env)
375
- mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
376
- if @last_check < mtime
377
- ActiveRecord::Migration.check_pending!
378
- @last_check = mtime
370
+ if connection.supports_migrations?
371
+ mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
372
+ if @last_check < mtime
373
+ ActiveRecord::Migration.check_pending!(connection)
374
+ @last_check = mtime
375
+ end
379
376
  end
380
377
  @app.call(env)
381
378
  end
379
+
380
+ private
381
+
382
+ def connection
383
+ ActiveRecord::Base.connection
384
+ end
382
385
  end
383
386
 
384
387
  class << self
@@ -390,7 +393,7 @@ module ActiveRecord
390
393
  end
391
394
 
392
395
  def load_schema_if_pending!
393
- if ActiveRecord::Migrator.needs_migration?
396
+ if ActiveRecord::Migrator.needs_migration? || !ActiveRecord::Migrator.any_migrations?
394
397
  # Roundrip to Rake to allow plugins to hook into database initialization.
395
398
  FileUtils.cd Rails.root do
396
399
  current_config = Base.connection_config
@@ -417,7 +420,10 @@ module ActiveRecord
417
420
  new.migrate direction
418
421
  end
419
422
 
420
- # Disable DDL transactions for this migration.
423
+ # Disable the transaction wrapping this migration.
424
+ # You can still create your own transactions even after calling #disable_ddl_transaction!
425
+ #
426
+ # For more details read the {"Transactional Migrations" section above}[rdoc-ref:Migration].
421
427
  def disable_ddl_transaction!
422
428
  @disable_ddl_transaction = true
423
429
  end
@@ -649,7 +655,10 @@ module ActiveRecord
649
655
  unless @connection.respond_to? :revert
650
656
  unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
651
657
  arguments[0] = proper_table_name(arguments.first, table_name_options)
652
- arguments[1] = proper_table_name(arguments.second, table_name_options) if method == :rename_table
658
+ if [:rename_table, :add_foreign_key].include?(method) ||
659
+ (method == :remove_foreign_key && !arguments.second.is_a?(Hash))
660
+ arguments[1] = proper_table_name(arguments.second, table_name_options)
661
+ end
653
662
  end
654
663
  end
655
664
  return super unless connection.respond_to?(method)
@@ -811,22 +820,22 @@ module ActiveRecord
811
820
  migrations = migrations(migrations_paths)
812
821
  migrations.select! { |m| yield m } if block_given?
813
822
 
814
- self.new(:up, migrations, target_version).migrate
823
+ new(:up, migrations, target_version).migrate
815
824
  end
816
825
 
817
826
  def down(migrations_paths, target_version = nil, &block)
818
827
  migrations = migrations(migrations_paths)
819
828
  migrations.select! { |m| yield m } if block_given?
820
829
 
821
- self.new(:down, migrations, target_version).migrate
830
+ new(:down, migrations, target_version).migrate
822
831
  end
823
832
 
824
833
  def run(direction, migrations_paths, target_version)
825
- self.new(direction, migrations(migrations_paths), target_version).run
834
+ new(direction, migrations(migrations_paths), target_version).run
826
835
  end
827
836
 
828
837
  def open(migrations_paths)
829
- self.new(:up, migrations(migrations_paths), nil)
838
+ new(:up, migrations(migrations_paths), nil)
830
839
  end
831
840
 
832
841
  def schema_migrations_table_name
@@ -849,6 +858,10 @@ module ActiveRecord
849
858
  (migrations(migrations_paths).collect(&:version) - get_all_versions(connection)).size > 0
850
859
  end
851
860
 
861
+ def any_migrations?
862
+ migrations(migrations_paths).any?
863
+ end
864
+
852
865
  def last_version
853
866
  last_migration.version
854
867
  end
@@ -857,19 +870,6 @@ module ActiveRecord
857
870
  migrations(migrations_paths).last || NullMigration.new
858
871
  end
859
872
 
860
- def proper_table_name(name, options = {})
861
- ActiveSupport::Deprecation.warn "ActiveRecord::Migrator.proper_table_name is deprecated and will be removed in Rails 4.2. Use the proper_table_name instance method on ActiveRecord::Migration instead"
862
- options = {
863
- table_name_prefix: ActiveRecord::Base.table_name_prefix,
864
- table_name_suffix: ActiveRecord::Base.table_name_suffix
865
- }.merge(options)
866
- if name.respond_to? :table_name
867
- name.table_name
868
- else
869
- "#{options[:table_name_prefix]}#{name}#{options[:table_name_suffix]}"
870
- end
871
- end
872
-
873
873
  def migrations_paths
874
874
  @migrations_paths ||= ['db/migrate']
875
875
  # just to not break things if someone uses: migration_path = some_string
@@ -880,14 +880,15 @@ module ActiveRecord
880
880
  migrations_paths.first
881
881
  end
882
882
 
883
+ def parse_migration_filename(filename) # :nodoc:
884
+ File.basename(filename).scan(/\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/).first
885
+ end
886
+
883
887
  def migrations(paths)
884
888
  paths = Array(paths)
885
889
 
886
- files = Dir[*paths.map { |p| "#{p}/**/[0-9]*_*.rb" }]
887
-
888
- migrations = files.map do |file|
889
- version, name, scope = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/).first
890
-
890
+ migrations = migration_files(paths).map do |file|
891
+ version, name, scope = parse_migration_filename(file)
891
892
  raise IllegalMigrationNameError.new(file) unless version
892
893
  version = version.to_i
893
894
  name = name.camelize
@@ -898,10 +899,34 @@ module ActiveRecord
898
899
  migrations.sort_by(&:version)
899
900
  end
900
901
 
902
+ def migrations_status(paths)
903
+ paths = Array(paths)
904
+
905
+ db_list = ActiveRecord::SchemaMigration.normalized_versions
906
+
907
+ file_list = migration_files(paths).map do |file|
908
+ version, name, scope = parse_migration_filename(file)
909
+ raise IllegalMigrationNameError.new(file) unless version
910
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
911
+ status = db_list.delete(version) ? "up" : "down"
912
+ [status, version, (name + scope).humanize]
913
+ end.compact
914
+
915
+ db_list.map! do |version|
916
+ ["up", version, "********** NO FILE **********"]
917
+ end
918
+
919
+ (db_list + file_list).sort_by { |_, version, _| version }
920
+ end
921
+
922
+ def migration_files(paths)
923
+ Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
924
+ end
925
+
901
926
  private
902
927
 
903
928
  def move(direction, migrations_paths, steps)
904
- migrator = self.new(direction, migrations(migrations_paths))
929
+ migrator = new(direction, migrations(migrations_paths))
905
930
  start_index = migrator.migrations.index(migrator.current_migration)
906
931
 
907
932
  if start_index