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,10 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
- # = Active Record Through Association
3
4
  module Associations
5
+ # = Active Record Through Association
4
6
  module ThroughAssociation #:nodoc:
5
- delegate :source_reflection, :through_reflection, to: :reflection
7
+ delegate :source_reflection, to: :reflection
6
8
 
7
9
  private
10
+ def through_reflection
11
+ @through_reflection ||= begin
12
+ refl = reflection.through_reflection
13
+
14
+ while refl.through_reflection?
15
+ refl = refl.through_reflection
16
+ end
17
+
18
+ refl
19
+ end
20
+ end
21
+
22
+ def through_association
23
+ @through_association ||= owner.association(through_reflection.name)
24
+ end
8
25
 
9
26
  # We merge in these scopes for two reasons:
10
27
  #
@@ -36,24 +53,22 @@ module ActiveRecord
36
53
  def construct_join_attributes(*records)
37
54
  ensure_mutable
38
55
 
39
- if source_reflection.association_primary_key(reflection.klass) == reflection.klass.primary_key
56
+ association_primary_key = source_reflection.association_primary_key(reflection.klass)
57
+
58
+ if association_primary_key == reflection.klass.primary_key && !options[:source_type]
40
59
  join_attributes = { source_reflection.name => records }
41
60
  else
42
61
  join_attributes = {
43
- source_reflection.foreign_key =>
44
- records.map { |record|
45
- record.send(source_reflection.association_primary_key(reflection.klass))
46
- }
62
+ source_reflection.foreign_key => records.map(&association_primary_key.to_sym)
47
63
  }
48
64
  end
49
65
 
50
66
  if options[:source_type]
51
- join_attributes[source_reflection.foreign_type] =
52
- records.map { |record| record.class.base_class.name }
67
+ join_attributes[source_reflection.foreign_type] = [ options[:source_type] ]
53
68
  end
54
69
 
55
70
  if records.count == 1
56
- Hash[join_attributes.map { |k, v| [k, v.first] }]
71
+ join_attributes.transform_values!(&:first)
57
72
  else
58
73
  join_attributes
59
74
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/enumerable"
2
4
  require "active_support/core_ext/string/conversions"
3
5
  require "active_support/core_ext/module/remove_method"
@@ -138,26 +140,6 @@ module ActiveRecord
138
140
  class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
139
141
  end
140
142
 
141
- class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc:
142
- def initialize(owner = nil, reflection = nil)
143
- if owner && reflection
144
- super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.")
145
- else
146
- super("Cannot associate new records.")
147
- end
148
- end
149
- end
150
-
151
- class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc:
152
- def initialize(owner = nil, reflection = nil)
153
- if owner && reflection
154
- super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.")
155
- else
156
- super("Cannot dissociate new records.")
157
- end
158
- end
159
- end
160
-
161
143
  class ThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc:
162
144
  def initialize(owner = nil, reflection = nil)
163
145
  if owner && reflection
@@ -187,16 +169,6 @@ module ActiveRecord
187
169
  end
188
170
  end
189
171
 
190
- class ReadOnlyAssociation < ActiveRecordError #:nodoc:
191
- def initialize(reflection = nil)
192
- if reflection
193
- super("Cannot add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.")
194
- else
195
- super("Read-only reflection error.")
196
- end
197
- end
198
- end
199
-
200
172
  # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
201
173
  # (has_many, has_one) when there is at least 1 child associated instance.
202
174
  # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
@@ -481,14 +453,14 @@ module ActiveRecord
481
453
  # The tables for these classes could look something like:
482
454
  #
483
455
  # CREATE TABLE users (
484
- # id int NOT NULL auto_increment,
485
- # account_id int default NULL,
456
+ # id bigint NOT NULL auto_increment,
457
+ # account_id bigint default NULL,
486
458
  # name varchar default NULL,
487
459
  # PRIMARY KEY (id)
488
460
  # )
489
461
  #
490
462
  # CREATE TABLE accounts (
491
- # id int NOT NULL auto_increment,
463
+ # id bigint NOT NULL auto_increment,
492
464
  # name varchar default NULL,
493
465
  # PRIMARY KEY (id)
494
466
  # )
@@ -555,9 +527,8 @@ module ActiveRecord
555
527
  # has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
556
528
  # end
557
529
  #
558
- # Note: Joining, eager loading and preloading of these associations is not fully possible.
530
+ # Note: Joining, eager loading and preloading of these associations is not possible.
559
531
  # These operations happen before instance creation and the scope will be called with a +nil+ argument.
560
- # This can lead to unexpected behavior and is deprecated.
561
532
  #
562
533
  # == Association callbacks
563
534
  #
@@ -848,7 +819,7 @@ module ActiveRecord
848
819
  # project.milestones # fetches milestones from the database
849
820
  # project.milestones.size # uses the milestone cache
850
821
  # project.milestones.empty? # uses the milestone cache
851
- # project.milestones(true).size # fetches milestones from the database
822
+ # project.milestones.reload.size # fetches milestones from the database
852
823
  # project.milestones # uses the milestone cache
853
824
  #
854
825
  # == Eager loading of associations
@@ -1090,12 +1061,6 @@ module ActiveRecord
1090
1061
  # belongs_to :dungeon, inverse_of: :evil_wizard
1091
1062
  # end
1092
1063
  #
1093
- # There are limitations to <tt>:inverse_of</tt> support:
1094
- #
1095
- # * does not work with <tt>:through</tt> associations.
1096
- # * does not work with <tt>:polymorphic</tt> associations.
1097
- # * inverse associations for #belongs_to associations #has_many are ignored.
1098
- #
1099
1064
  # For more information, see the documentation for the +:inverse_of+ option.
1100
1065
  #
1101
1066
  # == Deleting from associations
@@ -1189,7 +1154,7 @@ module ActiveRecord
1189
1154
  # +collection+ is a placeholder for the symbol passed as the +name+ argument, so
1190
1155
  # <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
1191
1156
  #
1192
- # [collection(force_reload = false)]
1157
+ # [collection]
1193
1158
  # Returns a Relation of all the associated objects.
1194
1159
  # An empty Relation is returned if none are found.
1195
1160
  # [collection<<(object, ...)]
@@ -1308,6 +1273,9 @@ module ActiveRecord
1308
1273
  # Specify the foreign key used for the association. By default this is guessed to be the name
1309
1274
  # of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_many
1310
1275
  # association will use "person_id" as the default <tt>:foreign_key</tt>.
1276
+ #
1277
+ # If you are going to modify the association (rather than just read from it), then it is
1278
+ # a good idea to set the <tt>:inverse_of</tt> option.
1311
1279
  # [:foreign_type]
1312
1280
  # Specify the column used to store the associated object's type, if this is a polymorphic
1313
1281
  # association. By default this is guessed to be the name of the polymorphic association
@@ -1381,8 +1349,7 @@ module ActiveRecord
1381
1349
  # <tt>:autosave</tt> to <tt>true</tt>.
1382
1350
  # [:inverse_of]
1383
1351
  # Specifies the name of the #belongs_to association on the associated object
1384
- # that is the inverse of this #has_many association. Does not work in combination
1385
- # with <tt>:through</tt> or <tt>:as</tt> options.
1352
+ # that is the inverse of this #has_many association.
1386
1353
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1387
1354
  # [:extend]
1388
1355
  # Specifies a module or array of modules that will be extended into the association object returned.
@@ -1398,7 +1365,7 @@ module ActiveRecord
1398
1365
  # has_many :tags, as: :taggable
1399
1366
  # has_many :reports, -> { readonly }
1400
1367
  # has_many :subscribers, through: :subscriptions, source: :user
1401
- def has_many(name, scope = nil, options = {}, &extension)
1368
+ def has_many(name, scope = nil, **options, &extension)
1402
1369
  reflection = Builder::HasMany.build(self, name, scope, options, &extension)
1403
1370
  Reflection.add_reflection self, name, reflection
1404
1371
  end
@@ -1478,6 +1445,9 @@ module ActiveRecord
1478
1445
  # Specify the foreign key used for the association. By default this is guessed to be the name
1479
1446
  # of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_one association
1480
1447
  # will use "person_id" as the default <tt>:foreign_key</tt>.
1448
+ #
1449
+ # If you are going to modify the association (rather than just read from it), then it is
1450
+ # a good idea to set the <tt>:inverse_of</tt> option.
1481
1451
  # [:foreign_type]
1482
1452
  # Specify the column used to store the associated object's type, if this is a polymorphic
1483
1453
  # association. By default this is guessed to be the name of the polymorphic association
@@ -1493,6 +1463,9 @@ module ActiveRecord
1493
1463
  # <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
1494
1464
  # source reflection. You can only use a <tt>:through</tt> query through a #has_one
1495
1465
  # or #belongs_to association on the join model.
1466
+ #
1467
+ # If you are going to modify the association (rather than just read from it), then it is
1468
+ # a good idea to set the <tt>:inverse_of</tt> option.
1496
1469
  # [:source]
1497
1470
  # Specifies the source association name used by #has_one <tt>:through</tt> queries.
1498
1471
  # Only use it if the name cannot be inferred from the association.
@@ -1513,8 +1486,7 @@ module ActiveRecord
1513
1486
  # <tt>:autosave</tt> to <tt>true</tt>.
1514
1487
  # [:inverse_of]
1515
1488
  # Specifies the name of the #belongs_to association on the associated object
1516
- # that is the inverse of this #has_one association. Does not work in combination
1517
- # with <tt>:through</tt> or <tt>:as</tt> options.
1489
+ # that is the inverse of this #has_one association.
1518
1490
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1519
1491
  # [:required]
1520
1492
  # When set to +true+, the association will also have its presence validated.
@@ -1532,7 +1504,7 @@ module ActiveRecord
1532
1504
  # has_one :club, through: :membership
1533
1505
  # has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
1534
1506
  # has_one :credit_card, required: true
1535
- def has_one(name, scope = nil, options = {})
1507
+ def has_one(name, scope = nil, **options)
1536
1508
  reflection = Builder::HasOne.build(self, name, scope, options)
1537
1509
  Reflection.add_reflection self, name, reflection
1538
1510
  end
@@ -1599,6 +1571,9 @@ module ActiveRecord
1599
1571
  # association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
1600
1572
  # <tt>belongs_to :favorite_person, class_name: "Person"</tt> will use a foreign key
1601
1573
  # of "favorite_person_id".
1574
+ #
1575
+ # If you are going to modify the association (rather than just read from it), then it is
1576
+ # a good idea to set the <tt>:inverse_of</tt> option.
1602
1577
  # [:foreign_type]
1603
1578
  # Specify the column used to store the associated object's type, if this is a polymorphic
1604
1579
  # association. By default this is guessed to be the name of the association with a "_type"
@@ -1648,8 +1623,7 @@ module ActiveRecord
1648
1623
  # +after_commit+ and +after_rollback+ callbacks are executed.
1649
1624
  # [:inverse_of]
1650
1625
  # Specifies the name of the #has_one or #has_many association on the associated
1651
- # object that is the inverse of this #belongs_to association. Does not work in
1652
- # combination with the <tt>:polymorphic</tt> options.
1626
+ # object that is the inverse of this #belongs_to association.
1653
1627
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1654
1628
  # [:optional]
1655
1629
  # When set to +true+, the association will not have its presence validated.
@@ -1676,7 +1650,7 @@ module ActiveRecord
1676
1650
  # belongs_to :company, touch: :employees_last_updated_at
1677
1651
  # belongs_to :user, optional: true
1678
1652
  # belongs_to :account, default: -> { company.account }
1679
- def belongs_to(name, scope = nil, options = {})
1653
+ def belongs_to(name, scope = nil, **options)
1680
1654
  reflection = Builder::BelongsTo.build(self, name, scope, options)
1681
1655
  Reflection.add_reflection self, name, reflection
1682
1656
  end
@@ -1818,6 +1792,9 @@ module ActiveRecord
1818
1792
  # of this class in lower-case and "_id" suffixed. So a Person class that makes
1819
1793
  # a #has_and_belongs_to_many association to Project will use "person_id" as the
1820
1794
  # default <tt>:foreign_key</tt>.
1795
+ #
1796
+ # If you are going to modify the association (rather than just read from it), then it is
1797
+ # a good idea to set the <tt>:inverse_of</tt> option.
1821
1798
  # [:association_foreign_key]
1822
1799
  # Specify the foreign key used for the association on the receiving side of the association.
1823
1800
  # By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
@@ -1846,7 +1823,7 @@ module ActiveRecord
1846
1823
 
1847
1824
  builder = Builder::HasAndBelongsToMany.new name, self, options
1848
1825
 
1849
- join_model = ActiveSupport::Deprecation.silence { builder.through_model }
1826
+ join_model = builder.through_model
1850
1827
 
1851
1828
  const_set join_model.name, join_model
1852
1829
  private_constant join_model.name
@@ -1875,7 +1852,7 @@ module ActiveRecord
1875
1852
  hm_options[k] = options[k] if options.key? k
1876
1853
  end
1877
1854
 
1878
- ActiveSupport::Deprecation.silence { has_many name, scope, hm_options, &extension }
1855
+ has_many name, scope, hm_options, &extension
1879
1856
  _reflections[name.to_s].parent_reflection = habtm_reflection
1880
1857
  end
1881
1858
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_model/forbidden_attributes_protection"
2
4
 
3
5
  module ActiveRecord
@@ -5,11 +7,6 @@ module ActiveRecord
5
7
  extend ActiveSupport::Concern
6
8
  include ActiveModel::AttributeAssignment
7
9
 
8
- # Alias for ActiveModel::AttributeAssignment#assign_attributes. See ActiveModel::AttributeAssignment.
9
- def attributes=(attributes)
10
- assign_attributes(attributes)
11
- end
12
-
13
10
  private
14
11
 
15
12
  def _assign_attributes(attributes)
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module AttributeDecorators # :nodoc:
3
5
  extend ActiveSupport::Concern
4
6
 
5
7
  included do
6
- class_attribute :attribute_type_decorations, instance_accessor: false # :internal:
7
- self.attribute_type_decorations = TypeDecorator.new
8
+ class_attribute :attribute_type_decorations, instance_accessor: false, default: TypeDecorator.new # :internal:
8
9
  end
9
10
 
10
11
  module ClassMethods # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module AttributeMethods
3
5
  # = Active Record Attribute Methods Before Type Cast
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "active_support/core_ext/module/attribute_accessors"
3
- require "active_record/attribute_mutation_tracker"
4
4
 
5
5
  module ActiveRecord
6
6
  module AttributeMethods
@@ -14,11 +14,10 @@ module ActiveRecord
14
14
  raise "You cannot include Dirty after Timestamp"
15
15
  end
16
16
 
17
- class_attribute :partial_writes, instance_writer: false
18
- self.partial_writes = true
17
+ class_attribute :partial_writes, instance_writer: false, default: true
19
18
 
20
- after_create { changes_internally_applied }
21
- after_update { changes_internally_applied }
19
+ after_create { changes_applied }
20
+ after_update { changes_applied }
22
21
 
23
22
  # Attribute methods for "changed in last call to save?"
24
23
  attribute_method_affix(prefix: "saved_change_to_", suffix: "?")
@@ -30,107 +29,18 @@ module ActiveRecord
30
29
  attribute_method_suffix("_change_to_be_saved", "_in_database")
31
30
  end
32
31
 
33
- # Attempts to +save+ the record and clears changed attributes if successful.
34
- def save(*)
35
- if status = super
36
- changes_applied
37
- end
38
- status
39
- end
40
-
41
- # Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
42
- def save!(*)
43
- super.tap do
44
- changes_applied
45
- end
46
- end
47
-
48
32
  # <tt>reload</tt> the record and clears changed attributes.
49
33
  def reload(*)
50
34
  super.tap do
51
- @previous_mutation_tracker = nil
52
- clear_mutation_trackers
53
- @changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
54
- end
55
- end
56
-
57
- def initialize_dup(other) # :nodoc:
58
- super
59
- @attributes = self.class._default_attributes.map do |attr|
60
- attr.with_value_from_user(@attributes.fetch_value(attr.name))
61
- end
62
- clear_mutation_trackers
63
- end
64
-
65
- def changes_internally_applied # :nodoc:
66
- @mutations_before_last_save = mutations_from_database
67
- forget_attribute_assignments
68
- @mutations_from_database = AttributeMutationTracker.new(@attributes)
69
- end
70
-
71
- def changes_applied # :nodoc:
72
- @previous_mutation_tracker = mutation_tracker
73
- @changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
74
- @mutation_tracker = nil
75
- @mutations_from_database = nil
76
- end
77
-
78
- def clear_changes_information # :nodoc:
79
- @previous_mutation_tracker = nil
80
- @changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
81
- forget_attribute_assignments
82
- clear_mutation_trackers
83
- end
84
-
85
- def raw_write_attribute(attr_name, *) # :nodoc:
86
- result = super
87
- clear_attribute_change(attr_name)
88
- result
89
- end
90
-
91
- def clear_attribute_changes(attr_names) # :nodoc:
92
- super
93
- attr_names.each do |attr_name|
94
- clear_attribute_change(attr_name)
95
- end
96
- end
97
-
98
- def changed_attributes # :nodoc:
99
- # This should only be set by methods which will call changed_attributes
100
- # multiple times when it is known that the computed value cannot change.
101
- if defined?(@cached_changed_attributes)
102
- @cached_changed_attributes
103
- else
104
- emit_warning_if_needed("changed_attributes", "saved_changes.transform_values(&:first)")
105
- super.reverse_merge(mutation_tracker.changed_values).freeze
106
- end
107
- end
108
-
109
- def changes # :nodoc:
110
- cache_changed_attributes do
111
- emit_warning_if_needed("changes", "saved_changes")
112
- super
113
- end
114
- end
115
-
116
- def previous_changes # :nodoc:
117
- unless previous_mutation_tracker.equal?(mutations_before_last_save)
118
- ActiveSupport::Deprecation.warn(<<-EOW.strip_heredoc)
119
- The behavior of `previous_changes` inside of after callbacks is
120
- deprecated without replacement. In the next release of Rails,
121
- this method inside of `after_save` will return the changes that
122
- were just saved.
123
- EOW
35
+ @previously_changed = ActiveSupport::HashWithIndifferentAccess.new
36
+ @mutations_before_last_save = nil
37
+ @attributes_changed_by_setter = ActiveSupport::HashWithIndifferentAccess.new
38
+ @mutations_from_database = nil
124
39
  end
125
- previous_mutation_tracker.changes
126
- end
127
-
128
- def attribute_changed_in_place?(attr_name) # :nodoc:
129
- mutation_tracker.changed_in_place?(attr_name)
130
40
  end
131
41
 
132
42
  # Did this attribute change when we last saved? This method can be invoked
133
- # as `saved_change_to_name?` instead of `saved_change_to_attribute?("name")`.
43
+ # as +saved_change_to_name?+ instead of <tt>saved_change_to_attribute?("name")</tt>.
134
44
  # Behaves similarly to +attribute_changed?+. This method is useful in
135
45
  # after callbacks to determine if the call to save changed a certain
136
46
  # attribute.
@@ -153,8 +63,8 @@ module ActiveRecord
153
63
  # Behaves similarly to +attribute_change+. This method is useful in after
154
64
  # callbacks, to see the change in an attribute that just occurred
155
65
  #
156
- # This method can be invoked as `saved_change_to_name` in instead of
157
- # `saved_change_to_attribute("name")`
66
+ # This method can be invoked as +saved_change_to_name+ in instead of
67
+ # <tt>saved_change_to_attribute("name")</tt>
158
68
  def saved_change_to_attribute(attr_name)
159
69
  mutations_before_last_save.change_to_attribute(attr_name)
160
70
  end
@@ -167,7 +77,7 @@ module ActiveRecord
167
77
  mutations_before_last_save.original_value(attr_name)
168
78
  end
169
79
 
170
- # Did the last call to `save` have any changes to change?
80
+ # Did the last call to +save+ have any changes to change?
171
81
  def saved_changes?
172
82
  mutations_before_last_save.any_changes?
173
83
  end
@@ -177,116 +87,46 @@ module ActiveRecord
177
87
  mutations_before_last_save.changes
178
88
  end
179
89
 
180
- # Alias for `attribute_changed?`
90
+ # Alias for +attribute_changed?+
181
91
  def will_save_change_to_attribute?(attr_name, **options)
182
92
  mutations_from_database.changed?(attr_name, **options)
183
93
  end
184
94
 
185
- # Alias for `attribute_change`
95
+ # Alias for +attribute_change+
186
96
  def attribute_change_to_be_saved(attr_name)
187
97
  mutations_from_database.change_to_attribute(attr_name)
188
98
  end
189
99
 
190
- # Alias for `attribute_was`
100
+ # Alias for +attribute_was+
191
101
  def attribute_in_database(attr_name)
192
102
  mutations_from_database.original_value(attr_name)
193
103
  end
194
104
 
195
- # Alias for `changed?`
105
+ # Alias for +changed?+
196
106
  def has_changes_to_save?
197
107
  mutations_from_database.any_changes?
198
108
  end
199
109
 
200
- # Alias for `changes`
110
+ # Alias for +changes+
201
111
  def changes_to_save
202
112
  mutations_from_database.changes
203
113
  end
204
114
 
205
- # Alias for `changed`
115
+ # Alias for +changed+
206
116
  def changed_attribute_names_to_save
207
- mutations_from_database.changed_attribute_names
117
+ changes_to_save.keys
208
118
  end
209
119
 
210
- # Alias for `changed_attributes`
120
+ # Alias for +changed_attributes+
211
121
  def attributes_in_database
212
- mutations_from_database.changed_values
213
- end
214
-
215
- def attribute_was(*)
216
- emit_warning_if_needed("attribute_was", "attribute_before_last_save")
217
- super
218
- end
219
-
220
- def attribute_change(*)
221
- emit_warning_if_needed("attribute_change", "saved_change_to_attribute")
222
- super
223
- end
224
-
225
- def attribute_changed?(*)
226
- emit_warning_if_needed("attribute_changed?", "saved_change_to_attribute?")
227
- super
228
- end
229
-
230
- def changed?(*)
231
- emit_warning_if_needed("changed?", "saved_changes?")
232
- super
233
- end
234
-
235
- def changed(*)
236
- emit_warning_if_needed("changed", "saved_changes.keys")
237
- super
122
+ changes_to_save.transform_values(&:first)
238
123
  end
239
124
 
240
125
  private
241
-
242
- def mutation_tracker
243
- unless defined?(@mutation_tracker)
244
- @mutation_tracker = nil
245
- end
246
- @mutation_tracker ||= AttributeMutationTracker.new(@attributes)
247
- end
248
-
249
- def emit_warning_if_needed(method_name, new_method_name)
250
- unless mutation_tracker.equal?(mutations_from_database)
251
- ActiveSupport::Deprecation.warn(<<-EOW.squish)
252
- The behavior of `#{method_name}` inside of after callbacks will
253
- be changing in the next version of Rails. The new return value will reflect the
254
- behavior of calling the method after `save` returned (e.g. the opposite of what
255
- it returns now). To maintain the current behavior, use `#{new_method_name}`
256
- instead.
257
- EOW
258
- end
259
- end
260
-
261
- def mutations_from_database
262
- unless defined?(@mutations_from_database)
263
- @mutations_from_database = nil
264
- end
265
- @mutations_from_database ||= mutation_tracker
266
- end
267
-
268
- def changes_include?(attr_name)
269
- super || mutation_tracker.changed?(attr_name)
270
- end
271
-
272
- def clear_attribute_change(attr_name)
273
- mutation_tracker.forget_change(attr_name)
274
- mutations_from_database.forget_change(attr_name)
275
- end
276
-
277
- def attribute_will_change!(attr_name)
278
- super
279
- if self.class.has_attribute?(attr_name)
280
- mutations_from_database.force_change(attr_name)
281
- else
282
- ActiveSupport::Deprecation.warn(<<-EOW.squish)
283
- #{attr_name} is not an attribute known to Active Record.
284
- This behavior is deprecated and will be removed in the next
285
- version of Rails. If you'd like #{attr_name} to be managed
286
- by Active Record, add `attribute :#{attr_name} to your class.
287
- EOW
288
- mutations_from_database.deprecated_force_change(attr_name)
289
- end
126
+ def write_attribute_without_type_cast(attr_name, _)
127
+ result = super
128
+ clear_attribute_change(attr_name)
129
+ result
290
130
  end
291
131
 
292
132
  def _update_record(*)
@@ -300,35 +140,6 @@ module ActiveRecord
300
140
  def keys_for_partial_write
301
141
  changed_attribute_names_to_save & self.class.column_names
302
142
  end
303
-
304
- def forget_attribute_assignments
305
- @attributes = @attributes.map(&:forgetting_assignment)
306
- end
307
-
308
- def clear_mutation_trackers
309
- @mutation_tracker = nil
310
- @mutations_from_database = nil
311
- @mutations_before_last_save = nil
312
- end
313
-
314
- def previous_mutation_tracker
315
- @previous_mutation_tracker ||= NullMutationTracker.instance
316
- end
317
-
318
- def mutations_before_last_save
319
- @mutations_before_last_save ||= previous_mutation_tracker
320
- end
321
-
322
- def cache_changed_attributes
323
- @cached_changed_attributes = changed_attributes
324
- yield
325
- ensure
326
- clear_changed_attributes_cache
327
- end
328
-
329
- def clear_changed_attributes_cache
330
- remove_instance_variable(:@cached_changed_attributes) if defined?(@cached_changed_attributes)
331
- end
332
143
  end
333
144
  end
334
145
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "set"
2
4
 
3
5
  module ActiveRecord
@@ -8,23 +10,22 @@ module ActiveRecord
8
10
  # Returns this record's primary key value wrapped in an array if one is
9
11
  # available.
10
12
  def to_key
11
- sync_with_transaction_state
12
13
  key = id
13
14
  [key] if key
14
15
  end
15
16
 
16
17
  # Returns the primary key value.
17
18
  def id
18
- if pk = self.class.primary_key
19
- sync_with_transaction_state
20
- _read_attribute(pk)
21
- end
19
+ sync_with_transaction_state
20
+ primary_key = self.class.primary_key
21
+ _read_attribute(primary_key) if primary_key
22
22
  end
23
23
 
24
24
  # Sets the primary key value.
25
25
  def id=(value)
26
26
  sync_with_transaction_state
27
- write_attribute(self.class.primary_key, value) if self.class.primary_key
27
+ primary_key = self.class.primary_key
28
+ _write_attribute(primary_key, value) if primary_key
28
29
  end
29
30
 
30
31
  # Queries the primary key value.