activerecord 5.1.7 → 5.2.0

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 +372 -765
  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 +16 -27
  11. data/lib/active_record/associations/association_scope.rb +38 -50
  12. data/lib/active_record/associations/belongs_to_association.rb +20 -10
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +4 -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 +43 -35
  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 +7 -18
  26. data/lib/active_record/associations/has_one_association.rb +4 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +8 -7
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
  31. data/lib/active_record/associations/join_dependency.rb +23 -43
  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 -10
  36. data/lib/active_record/associations/through_association.rb +25 -10
  37. data/lib/active_record/associations.rb +31 -54
  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 +8 -2
  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 +6 -5
  50. data/lib/active_record/autosave_association.rb +8 -11
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +8 -10
  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 +111 -38
  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 +13 -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 +57 -2
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -78
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +111 -183
  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 +11 -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 +3 -11
  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 +2 -0
  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 +4 -6
  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 +246 -110
  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 +58 -82
  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 +18 -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 +71 -1
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +80 -90
  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 +15 -12
  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 +54 -21
  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 +14 -17
  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 +16 -21
  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 +166 -16
  156. data/lib/active_record/query_cache.rb +11 -6
  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 +30 -8
  167. data/lib/active_record/relation/delegation.rb +15 -27
  168. data/lib/active_record/relation/finder_methods.rb +75 -78
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +51 -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 +53 -78
  179. data/lib/active_record/relation/query_attribute.rb +26 -2
  180. data/lib/active_record/relation/query_methods.rb +89 -88
  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 +95 -208
  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 +26 -15
  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 +5 -12
  206. data/lib/active_record/touch_later.rb +2 -0
  207. data/lib/active_record/transactions.rb +9 -7
  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 +2 -4
  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 +35 -5
  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 +24 -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 -122
  254. data/lib/active_record/attribute_set/builder.rb +0 -126
  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
 
@@ -115,27 +117,16 @@ module ActiveRecord
115
117
 
116
118
  # Raised when a foreign key constraint cannot be added because the column type does not match the referenced column type.
117
119
  class MismatchedForeignKey < StatementInvalid
118
- def initialize(
119
- adapter = nil,
120
- message: nil,
121
- sql: nil,
122
- binds: nil,
123
- table: nil,
124
- foreign_key: nil,
125
- target_table: nil,
126
- primary_key: nil,
127
- primary_key_column: nil
128
- )
120
+ def initialize(adapter = nil, message: nil, table: nil, foreign_key: nil, target_table: nil, primary_key: nil)
121
+ @adapter = adapter
129
122
  if table
130
- type = primary_key_column.bigint? ? :bigint : primary_key_column.type
131
- msg = <<-EOM.squish
132
- Column `#{foreign_key}` on table `#{table}` does not match column `#{primary_key}` on `#{target_table}`,
133
- which has type `#{primary_key_column.sql_type}`.
134
- To resolve this issue, change the type of the `#{foreign_key}` column on `#{table}` to be :#{type}.
135
- (For example `t.#{type} :#{foreign_key}`).
123
+ msg = <<-EOM.strip_heredoc
124
+ Column `#{foreign_key}` on table `#{table}` has a type of `#{column_type(table, foreign_key)}`.
125
+ This does not match column `#{primary_key}` on `#{target_table}`, which has type `#{column_type(target_table, primary_key)}`.
126
+ To resolve this issue, change the type of the `#{foreign_key}` column on `#{table}` to be :integer. (For example `t.integer #{foreign_key}`).
136
127
  EOM
137
128
  else
138
- msg = <<-EOM.squish
129
+ msg = <<-EOM
139
130
  There is a mismatch between the foreign key and primary key column types.
140
131
  Verify that the foreign key column type and the primary key of the associated table match types.
141
132
  EOM
@@ -145,6 +136,11 @@ module ActiveRecord
145
136
  end
146
137
  super(msg)
147
138
  end
139
+
140
+ private
141
+ def column_type(table, column)
142
+ @adapter.columns(table).detect { |c| c.name == column }.sql_type
143
+ end
148
144
  end
149
145
 
150
146
  # Raised when a record cannot be inserted or updated because it would violate a not null constraint.
@@ -173,7 +169,7 @@ module ActiveRecord
173
169
  class NoDatabaseError < StatementInvalid
174
170
  end
175
171
 
176
- # 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
177
173
  # we cannot retry gracefully (e.g. inside a transaction)
178
174
  class PreparedStatementCacheExpired < StatementInvalid
179
175
  end
@@ -319,7 +315,7 @@ module ActiveRecord
319
315
  #
320
316
  # See the following:
321
317
  #
322
- # * http://www.postgresql.org/docs/current/static/transaction-iso.html
318
+ # * https://www.postgresql.org/docs/current/static/transaction-iso.html
323
319
  # * https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html#error_er_lock_deadlock
324
320
  class TransactionRollbackError < StatementInvalid
325
321
  end
@@ -338,4 +334,41 @@ module ActiveRecord
338
334
  # +reverse_order+ to automatically reverse.
339
335
  class IrreversibleOrderError < ActiveRecordError
340
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
341
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 = 7
11
+ MINOR = 2
12
+ TINY = 0
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