activerecord 5.0.7.2 → 5.1.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 (216) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +389 -2252
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +28 -28
  6. data/examples/simple.rb +3 -3
  7. data/lib/active_record.rb +20 -20
  8. data/lib/active_record/aggregations.rb +244 -244
  9. data/lib/active_record/association_relation.rb +5 -5
  10. data/lib/active_record/associations.rb +1579 -1569
  11. data/lib/active_record/associations/alias_tracker.rb +1 -1
  12. data/lib/active_record/associations/association.rb +23 -15
  13. data/lib/active_record/associations/association_scope.rb +83 -81
  14. data/lib/active_record/associations/belongs_to_association.rb +0 -1
  15. data/lib/active_record/associations/builder/belongs_to.rb +16 -14
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -2
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
  18. data/lib/active_record/associations/collection_association.rb +74 -241
  19. data/lib/active_record/associations/collection_proxy.rb +144 -70
  20. data/lib/active_record/associations/has_many_association.rb +15 -19
  21. data/lib/active_record/associations/has_many_through_association.rb +12 -5
  22. data/lib/active_record/associations/has_one_association.rb +22 -28
  23. data/lib/active_record/associations/has_one_through_association.rb +5 -1
  24. data/lib/active_record/associations/join_dependency.rb +117 -115
  25. data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
  26. data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
  27. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  28. data/lib/active_record/associations/preloader.rb +94 -94
  29. data/lib/active_record/associations/preloader/association.rb +87 -64
  30. data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
  31. data/lib/active_record/associations/preloader/collection_association.rb +6 -6
  32. data/lib/active_record/associations/preloader/has_many.rb +0 -2
  33. data/lib/active_record/associations/preloader/singular_association.rb +6 -8
  34. data/lib/active_record/associations/preloader/through_association.rb +34 -41
  35. data/lib/active_record/associations/singular_association.rb +8 -25
  36. data/lib/active_record/associations/through_association.rb +3 -6
  37. data/lib/active_record/attribute.rb +98 -71
  38. data/lib/active_record/attribute/user_provided_default.rb +4 -2
  39. data/lib/active_record/attribute_assignment.rb +61 -61
  40. data/lib/active_record/attribute_decorators.rb +35 -13
  41. data/lib/active_record/attribute_methods.rb +56 -65
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
  43. data/lib/active_record/attribute_methods/dirty.rb +216 -34
  44. data/lib/active_record/attribute_methods/primary_key.rb +78 -73
  45. data/lib/active_record/attribute_methods/read.rb +39 -35
  46. data/lib/active_record/attribute_methods/serialization.rb +7 -7
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
  48. data/lib/active_record/attribute_methods/write.rb +36 -30
  49. data/lib/active_record/attribute_mutation_tracker.rb +53 -10
  50. data/lib/active_record/attribute_set.rb +9 -6
  51. data/lib/active_record/attribute_set/builder.rb +41 -49
  52. data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
  53. data/lib/active_record/attributes.rb +21 -21
  54. data/lib/active_record/autosave_association.rb +13 -13
  55. data/lib/active_record/base.rb +24 -22
  56. data/lib/active_record/callbacks.rb +52 -14
  57. data/lib/active_record/coders/yaml_column.rb +9 -11
  58. data/lib/active_record/collection_cache_key.rb +6 -17
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
  62. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
  63. data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
  64. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
  65. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
  66. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
  67. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
  68. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
  71. data/lib/active_record/connection_adapters/column.rb +27 -5
  72. data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
  73. data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -43
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +49 -31
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
  92. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
  93. data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
  94. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  95. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
  97. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +28 -30
  98. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
  100. data/lib/active_record/connection_adapters/postgresql/quoting.rb +38 -36
  101. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
  103. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
  104. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +161 -170
  105. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
  106. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
  107. data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
  108. data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
  109. data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
  110. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
  111. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -20
  112. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
  113. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
  114. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
  115. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +187 -130
  116. data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
  117. data/lib/active_record/connection_handling.rb +14 -26
  118. data/lib/active_record/core.rb +110 -93
  119. data/lib/active_record/counter_cache.rb +62 -13
  120. data/lib/active_record/define_callbacks.rb +20 -0
  121. data/lib/active_record/dynamic_matchers.rb +80 -79
  122. data/lib/active_record/enum.rb +8 -6
  123. data/lib/active_record/errors.rb +58 -15
  124. data/lib/active_record/explain.rb +1 -2
  125. data/lib/active_record/explain_registry.rb +1 -1
  126. data/lib/active_record/explain_subscriber.rb +7 -4
  127. data/lib/active_record/fixture_set/file.rb +11 -8
  128. data/lib/active_record/fixtures.rb +66 -53
  129. data/lib/active_record/gem_version.rb +3 -3
  130. data/lib/active_record/inheritance.rb +93 -79
  131. data/lib/active_record/integration.rb +7 -7
  132. data/lib/active_record/internal_metadata.rb +3 -16
  133. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  134. data/lib/active_record/locking/optimistic.rb +64 -56
  135. data/lib/active_record/locking/pessimistic.rb +10 -1
  136. data/lib/active_record/log_subscriber.rb +29 -29
  137. data/lib/active_record/migration.rb +155 -172
  138. data/lib/active_record/migration/command_recorder.rb +94 -94
  139. data/lib/active_record/migration/compatibility.rb +76 -37
  140. data/lib/active_record/migration/join_table.rb +6 -6
  141. data/lib/active_record/model_schema.rb +85 -119
  142. data/lib/active_record/nested_attributes.rb +200 -199
  143. data/lib/active_record/null_relation.rb +10 -33
  144. data/lib/active_record/persistence.rb +45 -38
  145. data/lib/active_record/query_cache.rb +4 -8
  146. data/lib/active_record/querying.rb +2 -3
  147. data/lib/active_record/railtie.rb +16 -17
  148. data/lib/active_record/railties/controller_runtime.rb +6 -2
  149. data/lib/active_record/railties/databases.rake +125 -140
  150. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  151. data/lib/active_record/readonly_attributes.rb +2 -2
  152. data/lib/active_record/reflection.rb +79 -96
  153. data/lib/active_record/relation.rb +72 -115
  154. data/lib/active_record/relation/batches.rb +87 -58
  155. data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
  156. data/lib/active_record/relation/calculations.rb +154 -160
  157. data/lib/active_record/relation/delegation.rb +30 -29
  158. data/lib/active_record/relation/finder_methods.rb +195 -226
  159. data/lib/active_record/relation/merger.rb +58 -62
  160. data/lib/active_record/relation/predicate_builder.rb +92 -89
  161. data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
  162. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
  163. data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
  164. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
  165. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
  166. data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
  167. data/lib/active_record/relation/query_attribute.rb +1 -1
  168. data/lib/active_record/relation/query_methods.rb +247 -295
  169. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  170. data/lib/active_record/relation/spawn_methods.rb +4 -5
  171. data/lib/active_record/relation/where_clause.rb +79 -65
  172. data/lib/active_record/relation/where_clause_factory.rb +47 -8
  173. data/lib/active_record/result.rb +29 -31
  174. data/lib/active_record/runtime_registry.rb +3 -3
  175. data/lib/active_record/sanitization.rb +182 -197
  176. data/lib/active_record/schema.rb +3 -3
  177. data/lib/active_record/schema_dumper.rb +14 -37
  178. data/lib/active_record/schema_migration.rb +3 -3
  179. data/lib/active_record/scoping.rb +9 -10
  180. data/lib/active_record/scoping/default.rb +87 -91
  181. data/lib/active_record/scoping/named.rb +16 -28
  182. data/lib/active_record/secure_token.rb +2 -2
  183. data/lib/active_record/statement_cache.rb +13 -15
  184. data/lib/active_record/store.rb +31 -32
  185. data/lib/active_record/suppressor.rb +2 -1
  186. data/lib/active_record/table_metadata.rb +9 -5
  187. data/lib/active_record/tasks/database_tasks.rb +72 -65
  188. data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
  189. data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
  190. data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
  191. data/lib/active_record/timestamp.rb +39 -25
  192. data/lib/active_record/touch_later.rb +1 -2
  193. data/lib/active_record/transactions.rb +98 -110
  194. data/lib/active_record/type.rb +17 -13
  195. data/lib/active_record/type/adapter_specific_registry.rb +46 -42
  196. data/lib/active_record/type/decimal_without_scale.rb +9 -0
  197. data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
  198. data/lib/active_record/type/serialized.rb +8 -8
  199. data/lib/active_record/type/text.rb +9 -0
  200. data/lib/active_record/type/time.rb +0 -1
  201. data/lib/active_record/type/type_map.rb +11 -15
  202. data/lib/active_record/type/unsigned_integer.rb +15 -0
  203. data/lib/active_record/type_caster.rb +2 -2
  204. data/lib/active_record/type_caster/connection.rb +8 -6
  205. data/lib/active_record/type_caster/map.rb +3 -1
  206. data/lib/active_record/validations.rb +4 -4
  207. data/lib/active_record/validations/associated.rb +1 -1
  208. data/lib/active_record/validations/presence.rb +2 -2
  209. data/lib/active_record/validations/uniqueness.rb +8 -39
  210. data/lib/active_record/version.rb +1 -1
  211. data/lib/rails/generators/active_record.rb +4 -4
  212. data/lib/rails/generators/active_record/migration.rb +2 -2
  213. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
  214. data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
  215. metadata +22 -13
  216. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -25,9 +25,9 @@ module ActiveRecord
25
25
  # You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
26
26
  def has_secure_token(attribute = :token)
27
27
  # Load securerandom only when has_secure_token is used.
28
- require 'active_support/core_ext/securerandom'
28
+ require "active_support/core_ext/securerandom"
29
29
  define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
30
- before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token) unless self.send("#{attribute}?")}
30
+ before_create { send("#{attribute}=", self.class.generate_unique_secure_token) unless send("#{attribute}?") }
31
31
  end
32
32
 
33
33
  def generate_unique_secure_token
@@ -1,5 +1,4 @@
1
1
  module ActiveRecord
2
-
3
2
  # Statement cache is used to cache a single statement in order to avoid creating the AST again.
4
3
  # Initializing the cache is done by passing the statement in the create block:
5
4
  #
@@ -8,12 +7,12 @@ module ActiveRecord
8
7
  # end
9
8
  #
10
9
  # The cached statement is executed by using the
11
- # [connection.execute]{rdoc-ref:ConnectionAdapters::DatabaseStatements#execute} method:
10
+ # {connection.execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute] method:
12
11
  #
13
12
  # cache.execute([], Book, Book.connection)
14
13
  #
15
14
  # The relation returned by the block is cached, and for each
16
- # [execute]{rdoc-ref:ConnectionAdapters::DatabaseStatements#execute}
15
+ # {execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute]
17
16
  # call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
18
17
  #
19
18
  # If you want to cache the statement without the values you can use the +bind+ method of the
@@ -40,28 +39,27 @@ module ActiveRecord
40
39
  end
41
40
 
42
41
  class PartialQuery < Query # :nodoc:
43
- def initialize values
42
+ def initialize(values)
44
43
  @values = values
45
- @indexes = values.each_with_index.find_all { |thing,i|
44
+ @indexes = values.each_with_index.find_all { |thing, i|
46
45
  Arel::Nodes::BindParam === thing
47
46
  }.map(&:last)
48
47
  end
49
48
 
50
49
  def sql_for(binds, connection)
51
50
  val = @values.dup
52
- binds = connection.prepare_binds_for_database(binds)
53
- @indexes.each { |i| val[i] = connection.quote(binds.shift) }
51
+ casted_binds = binds.map(&:value_for_database)
52
+ @indexes.each { |i| val[i] = connection.quote(casted_binds.shift) }
54
53
  val.join
55
54
  end
56
55
  end
57
56
 
58
- def self.query(visitor, ast)
59
- Query.new visitor.accept(ast, Arel::Collectors::SQLString.new).value
57
+ def self.query(sql)
58
+ Query.new(sql)
60
59
  end
61
60
 
62
- def self.partial_query(visitor, ast, collector)
63
- collected = visitor.accept(ast, collector).value
64
- PartialQuery.new collected
61
+ def self.partial_query(values)
62
+ PartialQuery.new(values)
65
63
  end
66
64
 
67
65
  class Params # :nodoc:
@@ -70,7 +68,7 @@ module ActiveRecord
70
68
 
71
69
  class BindMap # :nodoc:
72
70
  def initialize(bound_attributes)
73
- @indexes = []
71
+ @indexes = []
74
72
  @bound_attributes = bound_attributes
75
73
 
76
74
  bound_attributes.each_with_index do |attr, i|
@@ -82,7 +80,7 @@ module ActiveRecord
82
80
 
83
81
  def bind(values)
84
82
  bas = @bound_attributes.dup
85
- @indexes.each_with_index { |offset,i| bas[offset] = bas[offset].with_cast_value(values[i]) }
83
+ @indexes.each_with_index { |offset, i| bas[offset] = bas[offset].with_cast_value(values[i]) }
86
84
  bas
87
85
  end
88
86
  end
@@ -92,7 +90,7 @@ module ActiveRecord
92
90
  def self.create(connection, block = Proc.new)
93
91
  relation = block.call Params.new
94
92
  bind_map = BindMap.new relation.bound_attributes
95
- query_builder = connection.cacheable_query relation.arel
93
+ query_builder = connection.cacheable_query(self, relation.arel)
96
94
  new query_builder, bind_map
97
95
  end
98
96
 
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/hash/indifferent_access'
1
+ require "active_support/core_ext/hash/indifferent_access"
2
2
 
3
3
  module ActiveRecord
4
4
  # Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column.
@@ -78,7 +78,7 @@ module ActiveRecord
78
78
 
79
79
  module ClassMethods
80
80
  def store(store_attribute, options = {})
81
- serialize store_attribute, IndifferentCoder.new(options[:coder])
81
+ serialize store_attribute, IndifferentCoder.new(store_attribute, options[:coder])
82
82
  store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
83
83
  end
84
84
 
@@ -114,25 +114,24 @@ module ActiveRecord
114
114
 
115
115
  def stored_attributes
116
116
  parent = superclass.respond_to?(:stored_attributes) ? superclass.stored_attributes : {}
117
- if self.local_stored_attributes
118
- parent.merge!(self.local_stored_attributes) { |k, a, b| a | b }
117
+ if local_stored_attributes
118
+ parent.merge!(local_stored_attributes) { |k, a, b| a | b }
119
119
  end
120
120
  parent
121
121
  end
122
122
  end
123
123
 
124
- protected
125
- def read_store_attribute(store_attribute, key)
124
+ private
125
+ def read_store_attribute(store_attribute, key) # :doc:
126
126
  accessor = store_accessor_for(store_attribute)
127
127
  accessor.read(self, store_attribute, key)
128
128
  end
129
129
 
130
- def write_store_attribute(store_attribute, key, value)
130
+ def write_store_attribute(store_attribute, key, value) # :doc:
131
131
  accessor = store_accessor_for(store_attribute)
132
132
  accessor.write(self, store_attribute, key, value)
133
133
  end
134
134
 
135
- private
136
135
  def store_accessor_for(store_attribute)
137
136
  type_for_attribute(store_attribute.to_s).accessor
138
137
  end
@@ -177,34 +176,34 @@ module ActiveRecord
177
176
  end
178
177
  end
179
178
 
180
- class IndifferentCoder # :nodoc:
181
- def initialize(coder_or_class_name)
182
- @coder =
183
- if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
184
- coder_or_class_name
185
- else
186
- ActiveRecord::Coders::YAMLColumn.new(coder_or_class_name || Object)
187
- end
188
- end
179
+ class IndifferentCoder # :nodoc:
180
+ def initialize(attr_name, coder_or_class_name)
181
+ @coder =
182
+ if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
183
+ coder_or_class_name
184
+ else
185
+ ActiveRecord::Coders::YAMLColumn.new(attr_name, coder_or_class_name || Object)
186
+ end
187
+ end
189
188
 
190
- def dump(obj)
191
- @coder.dump self.class.as_indifferent_hash(obj)
192
- end
189
+ def dump(obj)
190
+ @coder.dump self.class.as_indifferent_hash(obj)
191
+ end
193
192
 
194
- def load(yaml)
195
- self.class.as_indifferent_hash(@coder.load(yaml || ''))
196
- end
193
+ def load(yaml)
194
+ self.class.as_indifferent_hash(@coder.load(yaml || ""))
195
+ end
197
196
 
198
- def self.as_indifferent_hash(obj)
199
- case obj
200
- when ActiveSupport::HashWithIndifferentAccess
201
- obj
202
- when Hash
203
- obj.with_indifferent_access
204
- else
205
- ActiveSupport::HashWithIndifferentAccess.new
197
+ def self.as_indifferent_hash(obj)
198
+ case obj
199
+ when ActiveSupport::HashWithIndifferentAccess
200
+ obj
201
+ when Hash
202
+ obj.with_indifferent_access
203
+ else
204
+ ActiveSupport::HashWithIndifferentAccess.new
205
+ end
206
206
  end
207
207
  end
208
- end
209
208
  end
210
209
  end
@@ -30,10 +30,11 @@ module ActiveRecord
30
30
 
31
31
  module ClassMethods
32
32
  def suppress(&block)
33
+ previous_state = SuppressorRegistry.suppressed[name]
33
34
  SuppressorRegistry.suppressed[name] = true
34
35
  yield
35
36
  ensure
36
- SuppressorRegistry.suppressed[name] = false
37
+ SuppressorRegistry.suppressed[name] = previous_state
37
38
  end
38
39
  end
39
40
 
@@ -10,9 +10,7 @@ module ActiveRecord
10
10
  end
11
11
 
12
12
  def resolve_column_aliases(hash)
13
- # This method is a hot spot, so for now, use Hash[] to dup the hash.
14
- # https://bugs.ruby-lang.org/issues/7166
15
- new_hash = Hash[hash]
13
+ new_hash = hash.dup
16
14
  hash.each do |key, _|
17
15
  if (key.is_a?(Symbol)) && klass.attribute_alias?(key)
18
16
  new_hash[klass.attribute_alias(key)] = new_hash.delete(key)
@@ -33,10 +31,14 @@ module ActiveRecord
33
31
  if klass
34
32
  klass.type_for_attribute(column_name.to_s)
35
33
  else
36
- Type::Value.new
34
+ Type.default_value
37
35
  end
38
36
  end
39
37
 
38
+ def has_column?(column_name)
39
+ klass && klass.columns_hash.key?(column_name.to_s)
40
+ end
41
+
40
42
  def associated_with?(association_name)
41
43
  klass && klass._reflect_on_association(association_name)
42
44
  end
@@ -62,8 +64,10 @@ module ActiveRecord
62
64
  association && association.polymorphic?
63
65
  end
64
66
 
67
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
68
+ # Workaround for Ruby 2.2 "private attribute?" warning.
65
69
  protected
66
70
 
67
- attr_reader :klass, :arel_table, :association
71
+ attr_reader :klass, :arel_table, :association
68
72
  end
69
73
  end
@@ -1,5 +1,3 @@
1
- require 'active_support/core_ext/string/filters'
2
-
3
1
  module ActiveRecord
4
2
  module Tasks # :nodoc:
5
3
  class DatabaseAlreadyExists < StandardError; end # :nodoc:
@@ -35,15 +33,25 @@ module ActiveRecord
35
33
  #
36
34
  # DatabaseTasks.create_current('production')
37
35
  module DatabaseTasks
36
+ ##
37
+ # :singleton-method:
38
+ # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:structure:dump
39
+ mattr_accessor :structure_dump_flags, instance_accessor: false
40
+
41
+ ##
42
+ # :singleton-method:
43
+ # Extra flags passed to database CLI tool when calling db:structure:load
44
+ mattr_accessor :structure_load_flags, instance_accessor: false
45
+
38
46
  extend self
39
47
 
40
48
  attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
41
49
  attr_accessor :database_configuration
42
50
 
43
- LOCAL_HOSTS = ['127.0.0.1', 'localhost']
51
+ LOCAL_HOSTS = ["127.0.0.1", "localhost"]
44
52
 
45
53
  def check_protected_environments!
46
- unless ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK']
54
+ unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
47
55
  current = ActiveRecord::Migrator.current_environment
48
56
  stored = ActiveRecord::Migrator.last_stored_environment
49
57
 
@@ -72,15 +80,15 @@ module ActiveRecord
72
80
  end
73
81
 
74
82
  def migrations_paths
75
- @migrations_paths ||= Rails.application.paths['db/migrate'].to_a
83
+ @migrations_paths ||= Rails.application.paths["db/migrate"].to_a
76
84
  end
77
85
 
78
86
  def fixtures_path
79
- @fixtures_path ||= if ENV['FIXTURES_PATH']
80
- File.join(root, ENV['FIXTURES_PATH'])
81
- else
82
- File.join(root, 'test', 'fixtures')
83
- end
87
+ @fixtures_path ||= if ENV["FIXTURES_PATH"]
88
+ File.join(root, ENV["FIXTURES_PATH"])
89
+ else
90
+ File.join(root, "test", "fixtures")
91
+ end
84
92
  end
85
93
 
86
94
  def root
@@ -96,7 +104,7 @@ module ActiveRecord
96
104
  end
97
105
 
98
106
  def current_config(options = {})
99
- options.reverse_merge! :env => env
107
+ options.reverse_merge! env: env
100
108
  if options.has_key?(:config)
101
109
  @current_config = options[:config]
102
110
  else
@@ -106,7 +114,7 @@ module ActiveRecord
106
114
 
107
115
  def create(*arguments)
108
116
  configuration = arguments.first
109
- class_for_adapter(configuration['adapter']).new(*arguments).create
117
+ class_for_adapter(configuration["adapter"]).new(*arguments).create
110
118
  $stdout.puts "Created database '#{configuration['database']}'"
111
119
  rescue DatabaseAlreadyExists
112
120
  $stderr.puts "Database '#{configuration['database']}' already exists"
@@ -120,7 +128,7 @@ module ActiveRecord
120
128
  old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
121
129
  each_local_configuration { |configuration| create configuration }
122
130
  if old_pool
123
- ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec)
131
+ ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec.to_hash)
124
132
  end
125
133
  end
126
134
 
@@ -133,7 +141,7 @@ module ActiveRecord
133
141
 
134
142
  def drop(*arguments)
135
143
  configuration = arguments.first
136
- class_for_adapter(configuration['adapter']).new(*arguments).drop
144
+ class_for_adapter(configuration["adapter"]).new(*arguments).drop
137
145
  $stdout.puts "Dropped database '#{configuration['database']}'"
138
146
  rescue ActiveRecord::NoDatabaseError
139
147
  $stderr.puts "Database '#{configuration['database']}' does not exist"
@@ -154,11 +162,9 @@ module ActiveRecord
154
162
  end
155
163
 
156
164
  def migrate
157
- raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
158
-
159
165
  verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
160
166
  version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
161
- scope = ENV['SCOPE']
167
+ scope = ENV["SCOPE"]
162
168
  verbose_was, Migration.verbose = Migration.verbose, verbose
163
169
  Migrator.migrate(migrations_paths, version) do |migration|
164
170
  scope.blank? || scope == migration.scope
@@ -174,7 +180,7 @@ module ActiveRecord
174
180
 
175
181
  def charset(*arguments)
176
182
  configuration = arguments.first
177
- class_for_adapter(configuration['adapter']).new(*arguments).charset
183
+ class_for_adapter(configuration["adapter"]).new(*arguments).charset
178
184
  end
179
185
 
180
186
  def collation_current(environment = env)
@@ -183,11 +189,11 @@ module ActiveRecord
183
189
 
184
190
  def collation(*arguments)
185
191
  configuration = arguments.first
186
- class_for_adapter(configuration['adapter']).new(*arguments).collation
192
+ class_for_adapter(configuration["adapter"]).new(*arguments).collation
187
193
  end
188
194
 
189
195
  def purge(configuration)
190
- class_for_adapter(configuration['adapter']).new(configuration).purge
196
+ class_for_adapter(configuration["adapter"]).new(configuration).purge
191
197
  end
192
198
 
193
199
  def purge_all
@@ -206,39 +212,31 @@ module ActiveRecord
206
212
  def structure_dump(*arguments)
207
213
  configuration = arguments.first
208
214
  filename = arguments.delete_at 1
209
- class_for_adapter(configuration['adapter']).new(*arguments).structure_dump(filename)
215
+ class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename, structure_dump_flags)
210
216
  end
211
217
 
212
218
  def structure_load(*arguments)
213
219
  configuration = arguments.first
214
220
  filename = arguments.delete_at 1
215
- class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)
221
+ class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
216
222
  end
217
223
 
218
- def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env) # :nodoc:
224
+ def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
219
225
  file ||= schema_file(format)
220
226
 
221
- check_schema_file(file)
222
- ActiveRecord::Base.establish_connection(configuration)
223
-
224
227
  case format
225
228
  when :ruby
229
+ check_schema_file(file)
230
+ ActiveRecord::Base.establish_connection(configuration)
226
231
  load(file)
227
232
  when :sql
233
+ check_schema_file(file)
228
234
  structure_load(configuration, file)
229
235
  else
230
236
  raise ArgumentError, "unknown format #{format.inspect}"
231
237
  end
232
238
  ActiveRecord::InternalMetadata.create_table
233
- ActiveRecord::InternalMetadata[:environment] = environment
234
- end
235
-
236
- def load_schema_for(*args)
237
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
238
- This method was renamed to `#load_schema` and will be removed in the future.
239
- Use `#load_schema` instead.
240
- MSG
241
- load_schema(*args)
239
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
242
240
  end
243
241
 
244
242
  def schema_file(format = ActiveRecord::Base.schema_format)
@@ -251,8 +249,8 @@ module ActiveRecord
251
249
  end
252
250
 
253
251
  def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
254
- each_current_configuration(environment) { |configuration, configuration_environment|
255
- load_schema configuration, format, file, configuration_environment
252
+ each_current_configuration(environment) { |configuration|
253
+ load_schema configuration, format, file
256
254
  }
257
255
  ActiveRecord::Base.establish_connection(environment.to_sym)
258
256
  end
@@ -260,7 +258,7 @@ module ActiveRecord
260
258
  def check_schema_file(filename)
261
259
  unless File.exist?(filename)
262
260
  message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
263
- message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails.root)
261
+ message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails)
264
262
  Kernel.abort message
265
263
  end
266
264
  end
@@ -269,48 +267,57 @@ module ActiveRecord
269
267
  if seed_loader
270
268
  seed_loader.load_seed
271
269
  else
272
- raise "You tried to load seed data, but no seed loader is specified. Please specify seed " +
273
- "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" +
270
+ raise "You tried to load seed data, but no seed loader is specified. Please specify seed " \
271
+ "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" \
274
272
  "Seed loader should respond to load_seed method"
275
273
  end
276
274
  end
277
275
 
276
+ # Dumps the schema cache in YAML format for the connection into the file
277
+ #
278
+ # ==== Examples:
279
+ # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
280
+ def dump_schema_cache(conn, filename)
281
+ conn.schema_cache.clear!
282
+ conn.data_sources.each { |table| conn.schema_cache.add(table) }
283
+ open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
284
+ end
285
+
278
286
  private
279
287
 
280
- def class_for_adapter(adapter)
281
- key = @tasks.keys.detect { |pattern| adapter[pattern] }
282
- unless key
283
- raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
288
+ def class_for_adapter(adapter)
289
+ key = @tasks.keys.detect { |pattern| adapter[pattern] }
290
+ unless key
291
+ raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
292
+ end
293
+ @tasks[key]
284
294
  end
285
- @tasks[key]
286
- end
287
-
288
- def each_current_configuration(environment)
289
- environments = [environment]
290
- environments << 'test' if environment == 'development'
291
295
 
292
- ActiveRecord::Base.configurations.slice(*environments).each do |configuration_environment, configuration|
293
- next unless configuration["database"]
296
+ def each_current_configuration(environment)
297
+ environments = [environment]
298
+ environments << "test" if environment == "development"
294
299
 
295
- yield configuration, configuration_environment
300
+ configurations = ActiveRecord::Base.configurations.values_at(*environments)
301
+ configurations.compact.each do |configuration|
302
+ yield configuration unless configuration["database"].blank?
303
+ end
296
304
  end
297
- end
298
305
 
299
- def each_local_configuration
300
- ActiveRecord::Base.configurations.each_value do |configuration|
301
- next unless configuration['database']
306
+ def each_local_configuration
307
+ ActiveRecord::Base.configurations.each_value do |configuration|
308
+ next unless configuration["database"]
302
309
 
303
- if local_database?(configuration)
304
- yield configuration
305
- else
306
- $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
310
+ if local_database?(configuration)
311
+ yield configuration
312
+ else
313
+ $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
314
+ end
307
315
  end
308
316
  end
309
- end
310
317
 
311
- def local_database?(configuration)
312
- configuration['host'].blank? || LOCAL_HOSTS.include?(configuration['host'])
313
- end
318
+ def local_database?(configuration)
319
+ configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
320
+ end
314
321
  end
315
322
  end
316
323
  end