activerecord 5.1.5 → 5.2.1

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 (261) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +450 -699
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record/aggregations.rb +6 -5
  8. data/lib/active_record/association_relation.rb +4 -2
  9. data/lib/active_record/associations/alias_tracker.rb +19 -27
  10. data/lib/active_record/associations/association.rb +33 -37
  11. data/lib/active_record/associations/association_scope.rb +38 -50
  12. data/lib/active_record/associations/belongs_to_association.rb +28 -9
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +14 -5
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +2 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +52 -41
  22. data/lib/active_record/associations/collection_proxy.rb +12 -15
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +3 -1
  25. data/lib/active_record/associations/has_many_through_association.rb +8 -19
  26. data/lib/active_record/associations/has_one_association.rb +12 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +13 -8
  28. data/lib/active_record/associations/join_dependency/join_association.rb +22 -67
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
  31. data/lib/active_record/associations/join_dependency.rb +48 -93
  32. data/lib/active_record/associations/preloader/association.rb +45 -61
  33. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  34. data/lib/active_record/associations/preloader.rb +17 -37
  35. data/lib/active_record/associations/singular_association.rb +14 -16
  36. data/lib/active_record/associations/through_association.rb +26 -11
  37. data/lib/active_record/associations.rb +40 -63
  38. data/lib/active_record/attribute_assignment.rb +2 -5
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  41. data/lib/active_record/attribute_methods/dirty.rb +25 -214
  42. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  43. data/lib/active_record/attribute_methods/query.rb +2 -0
  44. data/lib/active_record/attribute_methods/read.rb +9 -3
  45. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  47. data/lib/active_record/attribute_methods/write.rb +21 -9
  48. data/lib/active_record/attribute_methods.rb +65 -24
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +16 -14
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +12 -6
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +2 -0
  55. data/lib/active_record/collection_cache_key.rb +11 -7
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +157 -29
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -32
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +149 -78
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +92 -165
  69. data/lib/active_record/connection_adapters/column.rb +3 -1
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +6 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -2
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +248 -112
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -73
  117. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +20 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +79 -92
  126. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  127. data/lib/active_record/connection_handling.rb +4 -2
  128. data/lib/active_record/core.rb +39 -60
  129. data/lib/active_record/counter_cache.rb +20 -15
  130. data/lib/active_record/define_callbacks.rb +5 -3
  131. data/lib/active_record/dynamic_matchers.rb +9 -9
  132. data/lib/active_record/enum.rb +17 -13
  133. data/lib/active_record/errors.rb +42 -3
  134. data/lib/active_record/explain.rb +3 -1
  135. data/lib/active_record/explain_registry.rb +2 -0
  136. data/lib/active_record/explain_subscriber.rb +2 -0
  137. data/lib/active_record/fixture_set/file.rb +2 -0
  138. data/lib/active_record/fixtures.rb +67 -60
  139. data/lib/active_record/gem_version.rb +4 -2
  140. data/lib/active_record/inheritance.rb +49 -19
  141. data/lib/active_record/integration.rb +58 -19
  142. data/lib/active_record/internal_metadata.rb +2 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  144. data/lib/active_record/locking/optimistic.rb +30 -42
  145. data/lib/active_record/locking/pessimistic.rb +9 -6
  146. data/lib/active_record/log_subscriber.rb +43 -0
  147. data/lib/active_record/migration/command_recorder.rb +11 -9
  148. data/lib/active_record/migration/compatibility.rb +40 -2
  149. data/lib/active_record/migration/join_table.rb +2 -0
  150. data/lib/active_record/migration.rb +189 -139
  151. data/lib/active_record/model_schema.rb +19 -24
  152. data/lib/active_record/nested_attributes.rb +18 -6
  153. data/lib/active_record/no_touching.rb +3 -1
  154. data/lib/active_record/null_relation.rb +2 -0
  155. data/lib/active_record/persistence.rb +196 -48
  156. data/lib/active_record/query_cache.rb +12 -14
  157. data/lib/active_record/querying.rb +3 -1
  158. data/lib/active_record/railtie.rb +61 -3
  159. data/lib/active_record/railties/console_sandbox.rb +2 -0
  160. data/lib/active_record/railties/controller_runtime.rb +2 -0
  161. data/lib/active_record/railties/databases.rake +46 -36
  162. data/lib/active_record/readonly_attributes.rb +3 -2
  163. data/lib/active_record/reflection.rb +110 -192
  164. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  165. data/lib/active_record/relation/batches.rb +20 -5
  166. data/lib/active_record/relation/calculations.rb +31 -9
  167. data/lib/active_record/relation/delegation.rb +15 -27
  168. data/lib/active_record/relation/finder_methods.rb +71 -76
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +47 -20
  171. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  172. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  173. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  174. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  175. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  176. data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
  177. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  178. data/lib/active_record/relation/predicate_builder.rb +55 -79
  179. data/lib/active_record/relation/query_attribute.rb +26 -2
  180. data/lib/active_record/relation/query_methods.rb +95 -91
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +3 -1
  183. data/lib/active_record/relation/where_clause.rb +65 -68
  184. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  185. data/lib/active_record/relation.rb +106 -219
  186. data/lib/active_record/result.rb +2 -0
  187. data/lib/active_record/runtime_registry.rb +2 -0
  188. data/lib/active_record/sanitization.rb +129 -121
  189. data/lib/active_record/schema.rb +4 -2
  190. data/lib/active_record/schema_dumper.rb +36 -26
  191. data/lib/active_record/schema_migration.rb +2 -0
  192. data/lib/active_record/scoping/default.rb +6 -7
  193. data/lib/active_record/scoping/named.rb +21 -7
  194. data/lib/active_record/scoping.rb +9 -8
  195. data/lib/active_record/secure_token.rb +2 -0
  196. data/lib/active_record/serialization.rb +2 -0
  197. data/lib/active_record/statement_cache.rb +22 -12
  198. data/lib/active_record/store.rb +3 -1
  199. data/lib/active_record/suppressor.rb +2 -0
  200. data/lib/active_record/table_metadata.rb +12 -3
  201. data/lib/active_record/tasks/database_tasks.rb +25 -14
  202. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  203. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  204. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  205. data/lib/active_record/timestamp.rb +13 -6
  206. data/lib/active_record/touch_later.rb +2 -0
  207. data/lib/active_record/transactions.rb +32 -27
  208. data/lib/active_record/translation.rb +2 -0
  209. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  210. data/lib/active_record/type/date.rb +2 -0
  211. data/lib/active_record/type/date_time.rb +2 -0
  212. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  213. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  214. data/lib/active_record/type/internal/timezone.rb +2 -0
  215. data/lib/active_record/type/json.rb +30 -0
  216. data/lib/active_record/type/serialized.rb +6 -0
  217. data/lib/active_record/type/text.rb +2 -0
  218. data/lib/active_record/type/time.rb +2 -0
  219. data/lib/active_record/type/type_map.rb +2 -0
  220. data/lib/active_record/type/unsigned_integer.rb +2 -0
  221. data/lib/active_record/type.rb +4 -1
  222. data/lib/active_record/type_caster/connection.rb +2 -0
  223. data/lib/active_record/type_caster/map.rb +3 -1
  224. data/lib/active_record/type_caster.rb +2 -0
  225. data/lib/active_record/validations/absence.rb +2 -0
  226. data/lib/active_record/validations/associated.rb +2 -0
  227. data/lib/active_record/validations/length.rb +2 -0
  228. data/lib/active_record/validations/presence.rb +2 -0
  229. data/lib/active_record/validations/uniqueness.rb +36 -6
  230. data/lib/active_record/validations.rb +2 -0
  231. data/lib/active_record/version.rb +2 -0
  232. data/lib/active_record.rb +11 -4
  233. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  234. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  235. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  236. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  238. data/lib/rails/generators/active_record/migration.rb +2 -0
  239. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  240. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  242. data/lib/rails/generators/active_record.rb +3 -1
  243. metadata +23 -36
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  251. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  252. data/lib/active_record/attribute.rb +0 -240
  253. data/lib/active_record/attribute_mutation_tracker.rb +0 -114
  254. data/lib/active_record/attribute_set/builder.rb +0 -124
  255. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  256. data/lib/active_record/attribute_set.rb +0 -113
  257. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  258. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  259. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  260. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  261. data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/object/deep_dup"
2
4
 
3
5
  module ActiveRecord
@@ -95,8 +97,7 @@ module ActiveRecord
95
97
 
96
98
  module Enum
97
99
  def self.extended(base) # :nodoc:
98
- base.class_attribute(:defined_enums, instance_writer: false)
99
- base.defined_enums = {}
100
+ base.class_attribute(:defined_enums, instance_writer: false, default: {})
100
101
  end
101
102
 
102
103
  def inherited(base) # :nodoc:
@@ -154,11 +155,12 @@ module ActiveRecord
154
155
  definitions.each do |name, values|
155
156
  # statuses = { }
156
157
  enum_values = ActiveSupport::HashWithIndifferentAccess.new
157
- name = name.to_sym
158
+ name = name.to_s
158
159
 
159
160
  # def self.statuses() statuses end
160
- detect_enum_conflict!(name, name.to_s.pluralize, true)
161
- klass.singleton_class.send(:define_method, name.to_s.pluralize) { enum_values }
161
+ detect_enum_conflict!(name, name.pluralize, true)
162
+ singleton_class.send(:define_method, name.pluralize) { enum_values }
163
+ defined_enums[name] = enum_values
162
164
 
163
165
  detect_enum_conflict!(name, name)
164
166
  detect_enum_conflict!(name, "#{name}=")
@@ -170,7 +172,7 @@ module ActiveRecord
170
172
 
171
173
  _enum_methods_module.module_eval do
172
174
  pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
173
- pairs.each do |value, i|
175
+ pairs.each do |label, value|
174
176
  if enum_prefix == true
175
177
  prefix = "#{name}_"
176
178
  elsif enum_prefix
@@ -182,23 +184,23 @@ module ActiveRecord
182
184
  suffix = "_#{enum_suffix}"
183
185
  end
184
186
 
185
- value_method_name = "#{prefix}#{value}#{suffix}"
186
- enum_values[value] = i
187
+ value_method_name = "#{prefix}#{label}#{suffix}"
188
+ enum_values[label] = value
189
+ label = label.to_s
187
190
 
188
- # def active?() status == 0 end
191
+ # def active?() status == "active" end
189
192
  klass.send(:detect_enum_conflict!, name, "#{value_method_name}?")
190
- define_method("#{value_method_name}?") { self[attr] == value.to_s }
193
+ define_method("#{value_method_name}?") { self[attr] == label }
191
194
 
192
- # def active!() update! status: :active end
195
+ # def active!() update!(status: 0) end
193
196
  klass.send(:detect_enum_conflict!, name, "#{value_method_name}!")
194
197
  define_method("#{value_method_name}!") { update!(attr => value) }
195
198
 
196
- # scope :active, -> { where status: 0 }
199
+ # scope :active, -> { where(status: 0) }
197
200
  klass.send(:detect_enum_conflict!, name, value_method_name, true)
198
201
  klass.scope value_method_name, -> { where(attr => value) }
199
202
  end
200
203
  end
201
- defined_enums[name.to_s] = enum_values
202
204
  end
203
205
  end
204
206
 
@@ -219,6 +221,8 @@ module ActiveRecord
219
221
  def detect_enum_conflict!(enum_name, method_name, klass_method = false)
220
222
  if klass_method && dangerous_class_method?(method_name)
221
223
  raise_conflict_error(enum_name, method_name, type: "class")
224
+ elsif klass_method && method_defined_within?(method_name, Relation)
225
+ raise_conflict_error(enum_name, method_name, type: "class", source: Relation.name)
222
226
  elsif !klass_method && dangerous_attribute_method?(method_name)
223
227
  raise_conflict_error(enum_name, method_name)
224
228
  elsif !klass_method && method_defined_within?(method_name, _enum_methods_module, Module)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record Errors
3
5
  #
@@ -105,7 +107,7 @@ module ActiveRecord
105
107
  class WrappedDatabaseException < StatementInvalid
106
108
  end
107
109
 
108
- # Raised when a record cannot be inserted because it would violate a uniqueness constraint.
110
+ # Raised when a record cannot be inserted or updated because it would violate a uniqueness constraint.
109
111
  class RecordNotUnique < WrappedDatabaseException
110
112
  end
111
113
 
@@ -167,7 +169,7 @@ module ActiveRecord
167
169
  class NoDatabaseError < StatementInvalid
168
170
  end
169
171
 
170
- # Raised when Postgres returns 'cached plan must not change result type' and
172
+ # Raised when PostgreSQL returns 'cached plan must not change result type' and
171
173
  # we cannot retry gracefully (e.g. inside a transaction)
172
174
  class PreparedStatementCacheExpired < StatementInvalid
173
175
  end
@@ -313,7 +315,7 @@ module ActiveRecord
313
315
  #
314
316
  # See the following:
315
317
  #
316
- # * http://www.postgresql.org/docs/current/static/transaction-iso.html
318
+ # * https://www.postgresql.org/docs/current/static/transaction-iso.html
317
319
  # * https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html#error_er_lock_deadlock
318
320
  class TransactionRollbackError < StatementInvalid
319
321
  end
@@ -332,4 +334,41 @@ module ActiveRecord
332
334
  # +reverse_order+ to automatically reverse.
333
335
  class IrreversibleOrderError < ActiveRecordError
334
336
  end
337
+
338
+ # LockWaitTimeout will be raised when lock wait timeout exceeded.
339
+ class LockWaitTimeout < StatementInvalid
340
+ end
341
+
342
+ # StatementTimeout will be raised when statement timeout exceeded.
343
+ class StatementTimeout < StatementInvalid
344
+ end
345
+
346
+ # QueryCanceled will be raised when canceling statement due to user request.
347
+ class QueryCanceled < StatementInvalid
348
+ end
349
+
350
+ # UnknownAttributeReference is raised when an unknown and potentially unsafe
351
+ # value is passed to a query method when allow_unsafe_raw_sql is set to
352
+ # :disabled. For example, passing a non column name value to a relation's
353
+ # #order method might cause this exception.
354
+ #
355
+ # When working around this exception, caution should be taken to avoid SQL
356
+ # injection vulnerabilities when passing user-provided values to query
357
+ # methods. Known-safe values can be passed to query methods by wrapping them
358
+ # in Arel.sql.
359
+ #
360
+ # For example, with allow_unsafe_raw_sql set to :disabled, the following
361
+ # code would raise this exception:
362
+ #
363
+ # Post.order("length(title)").first
364
+ #
365
+ # The desired result can be accomplished by wrapping the known-safe string
366
+ # in Arel.sql:
367
+ #
368
+ # Post.order(Arel.sql("length(title)")).first
369
+ #
370
+ # Again, such a workaround should *not* be used when passing user-provided
371
+ # values, such as request parameters or model attributes to query methods.
372
+ class UnknownAttributeReference < ActiveRecordError
373
+ end
335
374
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record/explain_registry"
2
4
 
3
5
  module ActiveRecord
@@ -16,7 +18,7 @@ module ActiveRecord
16
18
  # Returns a formatted string ready to be logged.
17
19
  def exec_explain(queries) # :nodoc:
18
20
  str = queries.map do |sql, binds|
19
- msg = "EXPLAIN for: #{sql}"
21
+ msg = "EXPLAIN for: #{sql}".dup
20
22
  unless binds.empty?
21
23
  msg << " "
22
24
  msg << binds.map { |attr| render_bind(attr) }.inspect
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/per_thread_registry"
2
4
 
3
5
  module ActiveRecord
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/notifications"
2
4
  require "active_record/explain_registry"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "erb"
2
4
  require "yaml"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "erb"
2
4
  require "yaml"
3
5
  require "zlib"
@@ -70,13 +72,32 @@ module ActiveRecord
70
72
  # test. To ensure consistent data, the environment deletes the fixtures before running the load.
71
73
  #
72
74
  # In addition to being available in the database, the fixture's data may also be accessed by
73
- # using a special dynamic method, which has the same name as the model, and accepts the
74
- # name of the fixture to instantiate:
75
+ # using a special dynamic method, which has the same name as the model.
76
+ #
77
+ # Passing in a fixture name to this dynamic method returns the fixture matching this name:
75
78
  #
76
- # test "find" do
79
+ # test "find one" do
77
80
  # assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
78
81
  # end
79
82
  #
83
+ # Passing in multiple fixture names returns all fixtures matching these names:
84
+ #
85
+ # test "find all by name" do
86
+ # assert_equal 2, web_sites(:rubyonrails, :google).length
87
+ # end
88
+ #
89
+ # Passing in no arguments returns all fixtures:
90
+ #
91
+ # test "find all" do
92
+ # assert_equal 2, web_sites.length
93
+ # end
94
+ #
95
+ # Passing in any fixture name that does not exist will raise <tt>StandardError</tt>:
96
+ #
97
+ # test "find by name that does not exist" do
98
+ # assert_raise(StandardError) { web_sites(:reddit) }
99
+ # end
100
+ #
80
101
  # Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the
81
102
  # following tests:
82
103
  #
@@ -126,7 +147,7 @@ module ActiveRecord
126
147
  # unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module
127
148
  # that is included in ActiveRecord::FixtureSet.context_class.
128
149
  #
129
- # - define a helper method in `test_helper.rb`
150
+ # - define a helper method in <tt>test_helper.rb</tt>
130
151
  # module FixtureFileHelpers
131
152
  # def file_sha(path)
132
153
  # Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
@@ -148,13 +169,13 @@ module ActiveRecord
148
169
  # self.use_transactional_tests = true
149
170
  #
150
171
  # test "godzilla" do
151
- # assert !Foo.all.empty?
172
+ # assert_not_empty Foo.all
152
173
  # Foo.destroy_all
153
- # assert Foo.all.empty?
174
+ # assert_empty Foo.all
154
175
  # end
155
176
  #
156
177
  # test "godzilla aftermath" do
157
- # assert !Foo.all.empty?
178
+ # assert_not_empty Foo.all
158
179
  # end
159
180
  # end
160
181
  #
@@ -473,8 +494,7 @@ module ActiveRecord
473
494
  end
474
495
  end
475
496
 
476
- cattr_accessor :all_loaded_fixtures
477
- self.all_loaded_fixtures = {}
497
+ cattr_accessor :all_loaded_fixtures, default: {}
478
498
 
479
499
  class ClassCache
480
500
  def initialize(class_names, config)
@@ -520,49 +540,38 @@ module ActiveRecord
520
540
  }
521
541
 
522
542
  unless files_to_read.empty?
523
- connection.disable_referential_integrity do
524
- fixtures_map = {}
525
-
526
- fixture_sets = files_to_read.map do |fs_name|
527
- klass = class_names[fs_name]
528
- conn = klass ? klass.connection : connection
529
- fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
530
- conn,
531
- fs_name,
532
- klass,
533
- ::File.join(fixtures_directory, fs_name))
534
- end
535
-
536
- update_all_loaded_fixtures fixtures_map
537
-
538
- connection.transaction(requires_new: true) do
539
- deleted_tables = Hash.new { |h, k| h[k] = Set.new }
540
- fixture_sets.each do |fs|
541
- conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
542
- table_rows = fs.table_rows
543
+ fixtures_map = {}
544
+
545
+ fixture_sets = files_to_read.map do |fs_name|
546
+ klass = class_names[fs_name]
547
+ conn = klass ? klass.connection : connection
548
+ fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
549
+ conn,
550
+ fs_name,
551
+ klass,
552
+ ::File.join(fixtures_directory, fs_name))
553
+ end
543
554
 
544
- table_rows.each_key do |table|
545
- unless deleted_tables[conn].include? table
546
- conn.delete "DELETE FROM #{conn.quote_table_name(table)}", "Fixture Delete"
547
- end
548
- deleted_tables[conn] << table
549
- end
555
+ update_all_loaded_fixtures fixtures_map
556
+ fixture_sets_by_connection = fixture_sets.group_by { |fs| fs.model_class ? fs.model_class.connection : connection }
550
557
 
551
- table_rows.each do |fixture_set_name, rows|
552
- rows.each do |row|
553
- conn.insert_fixture(row, fixture_set_name)
554
- end
555
- end
558
+ fixture_sets_by_connection.each do |conn, set|
559
+ table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
556
560
 
557
- # Cap primary key sequences to max(pk).
558
- if conn.respond_to?(:reset_pk_sequence!)
559
- conn.reset_pk_sequence!(fs.table_name)
560
- end
561
+ set.each do |fs|
562
+ fs.table_rows.each do |table, rows|
563
+ table_rows_for_connection[table].unshift(*rows)
561
564
  end
562
565
  end
566
+ conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
563
567
 
564
- cache_fixtures(connection, fixtures_map)
568
+ # Cap primary key sequences to max(pk).
569
+ if conn.respond_to?(:reset_pk_sequence!)
570
+ set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
571
+ end
565
572
  end
573
+
574
+ cache_fixtures(connection, fixtures_map)
566
575
  end
567
576
  cached_fixtures(connection, fixture_set_names)
568
577
  end
@@ -859,20 +868,12 @@ module ActiveRecord
859
868
 
860
869
  included do
861
870
  class_attribute :fixture_path, instance_writer: false
862
- class_attribute :fixture_table_names
863
- class_attribute :fixture_class_names
864
- class_attribute :use_transactional_tests
865
- class_attribute :use_instantiated_fixtures # true, false, or :no_instances
866
- class_attribute :pre_loaded_fixtures
867
- class_attribute :config
868
-
869
- self.fixture_table_names = []
870
- self.use_instantiated_fixtures = false
871
- self.pre_loaded_fixtures = false
872
- self.config = ActiveRecord::Base
873
-
874
- self.fixture_class_names = {}
875
- self.use_transactional_tests = true
871
+ class_attribute :fixture_table_names, default: []
872
+ class_attribute :fixture_class_names, default: {}
873
+ class_attribute :use_transactional_tests, default: true
874
+ class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
875
+ class_attribute :pre_loaded_fixtures, default: false
876
+ class_attribute :config, default: ActiveRecord::Base
876
877
  end
877
878
 
878
879
  module ClassMethods
@@ -909,6 +910,8 @@ module ActiveRecord
909
910
 
910
911
  define_method(accessor_name) do |*fixture_names|
911
912
  force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
913
+ return_single_record = fixture_names.size == 1
914
+ fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
912
915
 
913
916
  @fixture_cache[fs_name] ||= {}
914
917
 
@@ -923,7 +926,7 @@ module ActiveRecord
923
926
  end
924
927
  end
925
928
 
926
- instances.size == 1 ? instances.first : instances
929
+ return_single_record ? instances.first : instances
927
930
  end
928
931
  private accessor_name
929
932
  end
@@ -1053,6 +1056,10 @@ class ActiveRecord::FixtureSet::RenderContext # :nodoc:
1053
1056
  def get_binding
1054
1057
  binding()
1055
1058
  end
1059
+
1060
+ def binary(path)
1061
+ %(!!binary "#{Base64.strict_encode64(File.read(path))}")
1062
+ end
1056
1063
  end
1057
1064
  end
1058
1065
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # Returns the version of the currently loaded Active Record as a <tt>Gem::Version</tt>
3
5
  def self.gem_version
@@ -6,8 +8,8 @@ module ActiveRecord
6
8
 
7
9
  module VERSION
8
10
  MAJOR = 5
9
- MINOR = 1
10
- TINY = 5
11
+ MINOR = 2
12
+ TINY = 1
11
13
  PRE = nil
12
14
 
13
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash/indifferent_access"
2
4
 
3
5
  module ActiveRecord
@@ -30,7 +32,7 @@ module ActiveRecord
30
32
  # for differentiating between them or reloading the right type with find.
31
33
  #
32
34
  # Note, all the attributes for all the cases are kept in the same table. Read more:
33
- # http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
35
+ # https://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
34
36
  #
35
37
  module Inheritance
36
38
  extend ActiveSupport::Concern
@@ -38,22 +40,20 @@ module ActiveRecord
38
40
  included do
39
41
  # Determines whether to store the full constant name including namespace when using STI.
40
42
  # This is true, by default.
41
- class_attribute :store_full_sti_class, instance_writer: false
42
- self.store_full_sti_class = true
43
+ class_attribute :store_full_sti_class, instance_writer: false, default: true
43
44
  end
44
45
 
45
46
  module ClassMethods
46
47
  # Determines if one of the attributes passed in is the inheritance column,
47
48
  # and if the inheritance column is attr accessible, it initializes an
48
49
  # instance of the given subclass instead of the base class.
49
- def new(*args, &block)
50
+ def new(attributes = nil, &block)
50
51
  if abstract_class? || self == Base
51
52
  raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
52
53
  end
53
54
 
54
- attrs = args.first
55
55
  if has_attribute?(inheritance_column)
56
- subclass = subclass_from_attributes(attrs)
56
+ subclass = subclass_from_attributes(attributes)
57
57
 
58
58
  if subclass.nil? && base_class == self
59
59
  subclass = subclass_from_attributes(column_defaults)
@@ -61,7 +61,7 @@ module ActiveRecord
61
61
  end
62
62
 
63
63
  if subclass && subclass != self
64
- subclass.new(*args, &block)
64
+ subclass.new(attributes, &block)
65
65
  else
66
66
  super
67
67
  end
@@ -104,21 +104,47 @@ module ActiveRecord
104
104
  end
105
105
  end
106
106
 
107
- # Set this to true if this is an abstract class (see <tt>abstract_class?</tt>).
108
- # If you are using inheritance with ActiveRecord and don't want child classes
109
- # to utilize the implied STI table name of the parent class, this will need to be true.
110
- # For example, given the following:
107
+ # Set this to +true+ if this is an abstract class (see
108
+ # <tt>abstract_class?</tt>).
109
+ # If you are using inheritance with Active Record and don't want a class
110
+ # to be considered as part of the STI hierarchy, you must set this to
111
+ # true.
112
+ # +ApplicationRecord+, for example, is generated as an abstract class.
113
+ #
114
+ # Consider the following default behaviour:
115
+ #
116
+ # Shape = Class.new(ActiveRecord::Base)
117
+ # Polygon = Class.new(Shape)
118
+ # Square = Class.new(Polygon)
119
+ #
120
+ # Shape.table_name # => "shapes"
121
+ # Polygon.table_name # => "shapes"
122
+ # Square.table_name # => "shapes"
123
+ # Shape.create! # => #<Shape id: 1, type: nil>
124
+ # Polygon.create! # => #<Polygon id: 2, type: "Polygon">
125
+ # Square.create! # => #<Square id: 3, type: "Square">
126
+ #
127
+ # However, when using <tt>abstract_class</tt>, +Shape+ is omitted from
128
+ # the hierarchy:
111
129
  #
112
- # class SuperClass < ActiveRecord::Base
130
+ # class Shape < ActiveRecord::Base
113
131
  # self.abstract_class = true
114
132
  # end
115
- # class Child < SuperClass
116
- # self.table_name = 'the_table_i_really_want'
117
- # end
118
- #
133
+ # Polygon = Class.new(Shape)
134
+ # Square = Class.new(Polygon)
119
135
  #
120
- # <tt>self.abstract_class = true</tt> is required to make <tt>Child<.find,.create, or any Arel method></tt> use <tt>the_table_i_really_want</tt> instead of a table called <tt>super_classes</tt>
136
+ # Shape.table_name # => nil
137
+ # Polygon.table_name # => "polygons"
138
+ # Square.table_name # => "polygons"
139
+ # Shape.create! # => NotImplementedError: Shape is an abstract class and cannot be instantiated.
140
+ # Polygon.create! # => #<Polygon id: 1, type: nil>
141
+ # Square.create! # => #<Square id: 2, type: "Square">
121
142
  #
143
+ # Note that in the above example, to disallow the creation of a plain
144
+ # +Polygon+, you should use <tt>validates :type, presence: true</tt>,
145
+ # instead of setting it as an abstract class. This way, +Polygon+ will
146
+ # stay in the hierarchy, and Active Record will continue to correctly
147
+ # derive the table name.
122
148
  attr_accessor :abstract_class
123
149
 
124
150
  # Returns whether this class is an abstract class or not.
@@ -130,6 +156,10 @@ module ActiveRecord
130
156
  store_full_sti_class ? name : name.demodulize
131
157
  end
132
158
 
159
+ def polymorphic_name
160
+ base_class.name
161
+ end
162
+
133
163
  def inherited(subclass)
134
164
  subclass.instance_variable_set(:@_type_candidates_cache, Concurrent::Map.new)
135
165
  super
@@ -217,7 +247,7 @@ module ActiveRecord
217
247
  def subclass_from_attributes(attrs)
218
248
  attrs = attrs.to_h if attrs.respond_to?(:permitted?)
219
249
  if attrs.is_a?(Hash)
220
- subclass_name = attrs.with_indifferent_access[inheritance_column]
250
+ subclass_name = attrs[inheritance_column] || attrs[inheritance_column.to_sym]
221
251
 
222
252
  if subclass_name.present?
223
253
  find_sti_class(subclass_name)
@@ -246,7 +276,7 @@ module ActiveRecord
246
276
  def ensure_proper_type
247
277
  klass = self.class
248
278
  if klass.finder_needs_type_condition?
249
- write_attribute(klass.inheritance_column, klass.sti_name)
279
+ _write_attribute(klass.inheritance_column, klass.sti_name)
250
280
  end
251
281
  end
252
282
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/string/filters"
2
4
 
3
5
  module ActiveRecord
@@ -7,12 +9,19 @@ module ActiveRecord
7
9
  included do
8
10
  ##
9
11
  # :singleton-method:
10
- # Indicates the format used to generate the timestamp in the cache key.
11
- # Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
12
+ # Indicates the format used to generate the timestamp in the cache key, if
13
+ # versioning is off. Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
12
14
  #
13
15
  # This is +:usec+, by default.
14
- class_attribute :cache_timestamp_format, instance_writer: false
15
- self.cache_timestamp_format = :usec
16
+ class_attribute :cache_timestamp_format, instance_writer: false, default: :usec
17
+
18
+ ##
19
+ # :singleton-method:
20
+ # Indicates whether to use a stable #cache_key method that is accompanied
21
+ # by a changing version in the #cache_version method.
22
+ #
23
+ # This is +false+, by default until Rails 6.0.
24
+ class_attribute :cache_versioning, instance_writer: false, default: false
16
25
  end
17
26
 
18
27
  # Returns a +String+, which Action Pack uses for constructing a URL to this
@@ -42,35 +51,65 @@ module ActiveRecord
42
51
  id && id.to_s # Be sure to stringify the id for routes
43
52
  end
44
53
 
45
- # Returns a cache key that can be used to identify this record.
54
+ # Returns a stable cache key that can be used to identify this record.
46
55
  #
47
56
  # Product.new.cache_key # => "products/new"
48
- # Product.find(5).cache_key # => "products/5" (updated_at not available)
49
- # Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available)
57
+ # Product.find(5).cache_key # => "products/5"
50
58
  #
51
- # You can also pass a list of named timestamps, and the newest in the list will be
52
- # used to generate the key:
59
+ # If ActiveRecord::Base.cache_versioning is turned off, as it was in Rails 5.1 and earlier,
60
+ # the cache key will also include a version.
53
61
  #
54
- # Person.find(5).cache_key(:updated_at, :last_reviewed_at)
62
+ # Product.cache_versioning = false
63
+ # Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available)
55
64
  def cache_key(*timestamp_names)
56
65
  if new_record?
57
66
  "#{model_name.cache_key}/new"
58
67
  else
59
- timestamp = if timestamp_names.any?
60
- max_updated_column_timestamp(timestamp_names)
68
+ if cache_version && timestamp_names.none?
69
+ "#{model_name.cache_key}/#{id}"
61
70
  else
62
- max_updated_column_timestamp
63
- end
71
+ timestamp = if timestamp_names.any?
72
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
73
+ Specifying a timestamp name for #cache_key has been deprecated in favor of
74
+ the explicit #cache_version method that can be overwritten.
75
+ MSG
64
76
 
65
- if timestamp
66
- timestamp = timestamp.utc.to_s(cache_timestamp_format)
67
- "#{model_name.cache_key}/#{id}-#{timestamp}"
68
- else
69
- "#{model_name.cache_key}/#{id}"
77
+ max_updated_column_timestamp(timestamp_names)
78
+ else
79
+ max_updated_column_timestamp
80
+ end
81
+
82
+ if timestamp
83
+ timestamp = timestamp.utc.to_s(cache_timestamp_format)
84
+ "#{model_name.cache_key}/#{id}-#{timestamp}"
85
+ else
86
+ "#{model_name.cache_key}/#{id}"
87
+ end
70
88
  end
71
89
  end
72
90
  end
73
91
 
92
+ # Returns a cache version that can be used together with the cache key to form
93
+ # a recyclable caching scheme. By default, the #updated_at column is used for the
94
+ # cache_version, but this method can be overwritten to return something else.
95
+ #
96
+ # Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to
97
+ # +false+ (which it is by default until Rails 6.0).
98
+ def cache_version
99
+ if cache_versioning && timestamp = try(:updated_at)
100
+ timestamp.utc.to_s(:usec)
101
+ end
102
+ end
103
+
104
+ # Returns a cache key along with the version.
105
+ def cache_key_with_version
106
+ if version = cache_version
107
+ "#{cache_key}-#{version}"
108
+ else
109
+ cache_key
110
+ end
111
+ end
112
+
74
113
  module ClassMethods
75
114
  # Defines your model's +to_param+ method to generate "pretty" URLs
76
115
  # using +method_name+, which can be any attribute or method that
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record/scoping/default"
2
4
  require "active_record/scoping/named"
3
5