activerecord 6.0.4.7 → 6.1.0.rc1

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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +764 -878
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_record/aggregations.rb +1 -1
  6. data/lib/active_record/association_relation.rb +22 -14
  7. data/lib/active_record/associations/alias_tracker.rb +19 -15
  8. data/lib/active_record/associations/association.rb +39 -27
  9. data/lib/active_record/associations/association_scope.rb +11 -15
  10. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  12. data/lib/active_record/associations/builder/association.rb +9 -3
  13. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  14. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
  16. data/lib/active_record/associations/builder/has_many.rb +6 -2
  17. data/lib/active_record/associations/builder/has_one.rb +11 -14
  18. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  19. data/lib/active_record/associations/collection_association.rb +19 -13
  20. data/lib/active_record/associations/collection_proxy.rb +12 -5
  21. data/lib/active_record/associations/foreign_association.rb +13 -0
  22. data/lib/active_record/associations/has_many_association.rb +24 -2
  23. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  24. data/lib/active_record/associations/has_one_association.rb +15 -1
  25. data/lib/active_record/associations/join_dependency/join_association.rb +29 -14
  26. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  27. data/lib/active_record/associations/join_dependency.rb +63 -49
  28. data/lib/active_record/associations/preloader/association.rb +13 -5
  29. data/lib/active_record/associations/preloader/through_association.rb +1 -1
  30. data/lib/active_record/associations/preloader.rb +5 -3
  31. data/lib/active_record/associations/singular_association.rb +1 -1
  32. data/lib/active_record/associations.rb +114 -11
  33. data/lib/active_record/attribute_assignment.rb +10 -8
  34. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
  35. data/lib/active_record/attribute_methods/dirty.rb +1 -11
  36. data/lib/active_record/attribute_methods/primary_key.rb +6 -2
  37. data/lib/active_record/attribute_methods/query.rb +3 -6
  38. data/lib/active_record/attribute_methods/read.rb +8 -11
  39. data/lib/active_record/attribute_methods/serialization.rb +4 -4
  40. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
  41. data/lib/active_record/attribute_methods/write.rb +12 -20
  42. data/lib/active_record/attribute_methods.rb +52 -48
  43. data/lib/active_record/attributes.rb +27 -7
  44. data/lib/active_record/autosave_association.rb +47 -30
  45. data/lib/active_record/base.rb +2 -14
  46. data/lib/active_record/callbacks.rb +32 -22
  47. data/lib/active_record/coders/yaml_column.rb +1 -1
  48. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +180 -134
  49. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  50. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
  51. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -7
  52. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  53. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  54. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  55. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +110 -30
  56. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +224 -85
  58. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -24
  59. data/lib/active_record/connection_adapters/abstract_adapter.rb +31 -70
  60. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +123 -87
  61. data/lib/active_record/connection_adapters/column.rb +15 -1
  62. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  63. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  64. data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -24
  65. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
  66. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  67. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +33 -6
  68. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  69. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  70. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -3
  71. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
  73. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  74. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  75. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  76. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +12 -53
  77. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  78. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  79. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -10
  80. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  88. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
  91. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  92. data/lib/active_record/connection_adapters/postgresql_adapter.rb +72 -55
  93. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  94. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  95. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +30 -5
  96. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  97. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  98. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +36 -3
  99. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +48 -50
  100. data/lib/active_record/connection_adapters.rb +50 -0
  101. data/lib/active_record/connection_handling.rb +210 -71
  102. data/lib/active_record/core.rb +215 -49
  103. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  104. data/lib/active_record/database_configurations/database_config.rb +52 -9
  105. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  106. data/lib/active_record/database_configurations/url_config.rb +15 -40
  107. data/lib/active_record/database_configurations.rb +124 -85
  108. data/lib/active_record/delegated_type.rb +209 -0
  109. data/lib/active_record/destroy_association_async_job.rb +36 -0
  110. data/lib/active_record/enum.rb +33 -23
  111. data/lib/active_record/errors.rb +47 -12
  112. data/lib/active_record/explain.rb +9 -4
  113. data/lib/active_record/explain_subscriber.rb +1 -1
  114. data/lib/active_record/fixture_set/file.rb +10 -17
  115. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  116. data/lib/active_record/fixture_set/render_context.rb +1 -1
  117. data/lib/active_record/fixture_set/table_row.rb +2 -2
  118. data/lib/active_record/fixtures.rb +54 -8
  119. data/lib/active_record/gem_version.rb +3 -3
  120. data/lib/active_record/inheritance.rb +40 -18
  121. data/lib/active_record/insert_all.rb +32 -5
  122. data/lib/active_record/integration.rb +3 -5
  123. data/lib/active_record/internal_metadata.rb +15 -4
  124. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  125. data/lib/active_record/locking/optimistic.rb +13 -16
  126. data/lib/active_record/locking/pessimistic.rb +6 -2
  127. data/lib/active_record/log_subscriber.rb +26 -8
  128. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  129. data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
  130. data/lib/active_record/middleware/database_selector.rb +4 -1
  131. data/lib/active_record/migration/command_recorder.rb +47 -27
  132. data/lib/active_record/migration/compatibility.rb +67 -17
  133. data/lib/active_record/migration.rb +113 -83
  134. data/lib/active_record/model_schema.rb +88 -42
  135. data/lib/active_record/nested_attributes.rb +2 -3
  136. data/lib/active_record/no_touching.rb +1 -1
  137. data/lib/active_record/persistence.rb +50 -45
  138. data/lib/active_record/query_cache.rb +15 -5
  139. data/lib/active_record/querying.rb +11 -6
  140. data/lib/active_record/railtie.rb +64 -44
  141. data/lib/active_record/railties/databases.rake +253 -98
  142. data/lib/active_record/readonly_attributes.rb +4 -0
  143. data/lib/active_record/reflection.rb +59 -44
  144. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  145. data/lib/active_record/relation/batches.rb +38 -31
  146. data/lib/active_record/relation/calculations.rb +100 -43
  147. data/lib/active_record/relation/finder_methods.rb +44 -14
  148. data/lib/active_record/relation/from_clause.rb +1 -1
  149. data/lib/active_record/relation/merger.rb +20 -23
  150. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  151. data/lib/active_record/relation/predicate_builder/association_query_value.rb +2 -2
  152. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
  153. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  154. data/lib/active_record/relation/predicate_builder.rb +57 -33
  155. data/lib/active_record/relation/query_methods.rb +319 -196
  156. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  157. data/lib/active_record/relation/spawn_methods.rb +6 -5
  158. data/lib/active_record/relation/where_clause.rb +104 -57
  159. data/lib/active_record/relation.rb +90 -64
  160. data/lib/active_record/result.rb +41 -33
  161. data/lib/active_record/runtime_registry.rb +2 -2
  162. data/lib/active_record/sanitization.rb +6 -17
  163. data/lib/active_record/schema_dumper.rb +34 -4
  164. data/lib/active_record/schema_migration.rb +0 -4
  165. data/lib/active_record/scoping/named.rb +1 -17
  166. data/lib/active_record/secure_token.rb +16 -8
  167. data/lib/active_record/serialization.rb +5 -3
  168. data/lib/active_record/signed_id.rb +116 -0
  169. data/lib/active_record/statement_cache.rb +20 -4
  170. data/lib/active_record/store.rb +2 -2
  171. data/lib/active_record/suppressor.rb +2 -2
  172. data/lib/active_record/table_metadata.rb +36 -52
  173. data/lib/active_record/tasks/database_tasks.rb +139 -113
  174. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
  175. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
  176. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
  177. data/lib/active_record/test_databases.rb +5 -4
  178. data/lib/active_record/test_fixtures.rb +36 -33
  179. data/lib/active_record/timestamp.rb +4 -6
  180. data/lib/active_record/touch_later.rb +21 -21
  181. data/lib/active_record/transactions.rb +15 -64
  182. data/lib/active_record/type/serialized.rb +6 -2
  183. data/lib/active_record/type.rb +8 -1
  184. data/lib/active_record/type_caster/connection.rb +0 -1
  185. data/lib/active_record/type_caster/map.rb +8 -5
  186. data/lib/active_record/validations/associated.rb +1 -1
  187. data/lib/active_record/validations/numericality.rb +35 -0
  188. data/lib/active_record/validations/uniqueness.rb +24 -4
  189. data/lib/active_record/validations.rb +1 -0
  190. data/lib/active_record.rb +7 -14
  191. data/lib/arel/attributes/attribute.rb +4 -0
  192. data/lib/arel/collectors/bind.rb +5 -0
  193. data/lib/arel/collectors/composite.rb +8 -0
  194. data/lib/arel/collectors/sql_string.rb +7 -0
  195. data/lib/arel/collectors/substitute_binds.rb +7 -0
  196. data/lib/arel/nodes/binary.rb +82 -8
  197. data/lib/arel/nodes/bind_param.rb +8 -0
  198. data/lib/arel/nodes/casted.rb +21 -9
  199. data/lib/arel/nodes/equality.rb +6 -9
  200. data/lib/arel/nodes/grouping.rb +3 -0
  201. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  202. data/lib/arel/nodes/in.rb +8 -1
  203. data/lib/arel/nodes/infix_operation.rb +13 -1
  204. data/lib/arel/nodes/join_source.rb +1 -1
  205. data/lib/arel/nodes/node.rb +7 -6
  206. data/lib/arel/nodes/ordering.rb +27 -0
  207. data/lib/arel/nodes/sql_literal.rb +3 -0
  208. data/lib/arel/nodes/table_alias.rb +7 -3
  209. data/lib/arel/nodes/unary.rb +0 -1
  210. data/lib/arel/nodes.rb +3 -1
  211. data/lib/arel/predications.rb +12 -18
  212. data/lib/arel/select_manager.rb +1 -2
  213. data/lib/arel/table.rb +13 -5
  214. data/lib/arel/visitors/dot.rb +14 -2
  215. data/lib/arel/visitors/mysql.rb +11 -1
  216. data/lib/arel/visitors/postgresql.rb +15 -4
  217. data/lib/arel/visitors/to_sql.rb +89 -78
  218. data/lib/arel/visitors.rb +0 -7
  219. data/lib/arel.rb +5 -13
  220. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  221. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  222. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
  223. data/lib/rails/generators/active_record/migration.rb +6 -1
  224. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  225. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  226. metadata +30 -31
  227. data/lib/active_record/advisory_lock_base.rb +0 -18
  228. data/lib/active_record/attribute_decorators.rb +0 -88
  229. data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
  230. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  231. data/lib/active_record/define_callbacks.rb +0 -22
  232. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  233. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  234. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  235. data/lib/arel/attributes.rb +0 -22
  236. data/lib/arel/visitors/depth_first.rb +0 -203
  237. data/lib/arel/visitors/ibm_db.rb +0 -34
  238. data/lib/arel/visitors/informix.rb +0 -62
  239. data/lib/arel/visitors/mssql.rb +0 -156
  240. data/lib/arel/visitors/oracle.rb +0 -158
  241. data/lib/arel/visitors/oracle12.rb +0 -65
  242. data/lib/arel/visitors/where_sql.rb +0 -22
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "mutex_m"
4
+ require "active_support/core_ext/enumerable"
4
5
 
5
6
  module ActiveRecord
6
7
  # = Active Record Attribute Methods
@@ -18,8 +19,6 @@ module ActiveRecord
18
19
  include TimeZoneConversion
19
20
  include Dirty
20
21
  include Serialization
21
-
22
- delegate :column_for_attribute, to: :class
23
22
  end
24
23
 
25
24
  RESTRICTED_CLASS_METHODS = %w(private public protected allocate new name parent superclass)
@@ -28,6 +27,17 @@ module ActiveRecord
28
27
  include Mutex_m
29
28
  end
30
29
 
30
+ class << self
31
+ def dangerous_attribute_methods # :nodoc:
32
+ @dangerous_attribute_methods ||= (
33
+ Base.instance_methods +
34
+ Base.private_instance_methods -
35
+ Base.superclass.instance_methods -
36
+ Base.superclass.private_instance_methods
37
+ ).map { |m| -m.to_s }.to_set.freeze
38
+ end
39
+ end
40
+
31
41
  module ClassMethods
32
42
  def inherited(child_class) #:nodoc:
33
43
  child_class.initialize_generated_modules
@@ -97,7 +107,7 @@ module ActiveRecord
97
107
  # A method name is 'dangerous' if it is already (re)defined by Active Record, but
98
108
  # not by any ancestors. (So 'puts' is not dangerous but 'save' is.)
99
109
  def dangerous_attribute_method?(name) # :nodoc:
100
- method_defined_within?(name, Base)
110
+ ::ActiveRecord::AttributeMethods.dangerous_attribute_methods.include?(name.to_s)
101
111
  end
102
112
 
103
113
  def method_defined_within?(name, klass, superklass = klass.superclass) # :nodoc:
@@ -115,13 +125,11 @@ module ActiveRecord
115
125
  # A class method is 'dangerous' if it is already (re)defined by Active Record, but
116
126
  # not by any ancestors. (So 'puts' is not dangerous but 'new' is.)
117
127
  def dangerous_class_method?(method_name)
118
- RESTRICTED_CLASS_METHODS.include?(method_name.to_s) || class_method_defined_within?(method_name, Base)
119
- end
128
+ return true if RESTRICTED_CLASS_METHODS.include?(method_name.to_s)
120
129
 
121
- def class_method_defined_within?(name, klass, superklass = klass.superclass) # :nodoc:
122
- if klass.respond_to?(name, true)
123
- if superklass.respond_to?(name, true)
124
- klass.method(name).owner != superklass.method(name).owner
130
+ if Base.respond_to?(method_name, true)
131
+ if Object.respond_to?(method_name, true)
132
+ Base.method(method_name).owner != Object.method(method_name).owner
125
133
  else
126
134
  true
127
135
  end
@@ -140,7 +148,7 @@ module ActiveRecord
140
148
  # Person.attribute_method?(:age=) # => true
141
149
  # Person.attribute_method?(:nothing) # => false
142
150
  def attribute_method?(attribute)
143
- super || (table_exists? && column_names.include?(attribute.to_s.sub(/=$/, "")))
151
+ super || (table_exists? && column_names.include?(attribute.to_s.delete_suffix("=")))
144
152
  end
145
153
 
146
154
  # Returns an array of column names as strings if it's not an abstract class and
@@ -156,39 +164,27 @@ module ActiveRecord
156
164
  attribute_types.keys
157
165
  else
158
166
  []
159
- end
167
+ end.freeze
160
168
  end
161
169
 
162
170
  # Returns true if the given attribute exists, otherwise false.
163
171
  #
164
172
  # class Person < ActiveRecord::Base
173
+ # alias_attribute :new_name, :name
165
174
  # end
166
175
  #
167
- # Person.has_attribute?('name') # => true
168
- # Person.has_attribute?(:age) # => true
169
- # Person.has_attribute?(:nothing) # => false
176
+ # Person.has_attribute?('name') # => true
177
+ # Person.has_attribute?('new_name') # => true
178
+ # Person.has_attribute?(:age) # => true
179
+ # Person.has_attribute?(:nothing) # => false
170
180
  def has_attribute?(attr_name)
171
- attribute_types.key?(attr_name.to_s)
181
+ attr_name = attr_name.to_s
182
+ attr_name = attribute_aliases[attr_name] || attr_name
183
+ attribute_types.key?(attr_name)
172
184
  end
173
185
 
174
- # Returns the column object for the named attribute.
175
- # Returns a +ActiveRecord::ConnectionAdapters::NullColumn+ if the
176
- # named attribute does not exist.
177
- #
178
- # class Person < ActiveRecord::Base
179
- # end
180
- #
181
- # person = Person.new
182
- # person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
183
- # # => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
184
- #
185
- # person.column_for_attribute(:nothing)
186
- # # => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
187
- def column_for_attribute(name)
188
- name = name.to_s
189
- columns_hash.fetch(name) do
190
- ConnectionAdapters::NullColumn.new(name)
191
- end
186
+ def _has_attribute?(attr_name) # :nodoc:
187
+ attribute_types.key?(attr_name)
192
188
  end
193
189
  end
194
190
 
@@ -217,7 +213,7 @@ module ActiveRecord
217
213
  # have been allocated but not yet initialized.
218
214
  if defined?(@attributes)
219
215
  if name = self.class.symbol_column_to_string(name.to_sym)
220
- return has_attribute?(name)
216
+ return _has_attribute?(name)
221
217
  end
222
218
  end
223
219
 
@@ -227,14 +223,22 @@ module ActiveRecord
227
223
  # Returns +true+ if the given attribute is in the attributes hash, otherwise +false+.
228
224
  #
229
225
  # class Person < ActiveRecord::Base
226
+ # alias_attribute :new_name, :name
230
227
  # end
231
228
  #
232
229
  # person = Person.new
233
- # person.has_attribute?(:name) # => true
234
- # person.has_attribute?('age') # => true
235
- # person.has_attribute?(:nothing) # => false
230
+ # person.has_attribute?(:name) # => true
231
+ # person.has_attribute?(:new_name) # => true
232
+ # person.has_attribute?('age') # => true
233
+ # person.has_attribute?(:nothing) # => false
236
234
  def has_attribute?(attr_name)
237
- @attributes.key?(attr_name.to_s)
235
+ attr_name = attr_name.to_s
236
+ attr_name = self.class.attribute_aliases[attr_name] || attr_name
237
+ @attributes.key?(attr_name)
238
+ end
239
+
240
+ def _has_attribute?(attr_name) # :nodoc:
241
+ @attributes.key?(attr_name)
238
242
  end
239
243
 
240
244
  # Returns an array of names for the attributes available on this object.
@@ -278,6 +282,8 @@ module ActiveRecord
278
282
  # person.attribute_for_inspect(:tag_ids)
279
283
  # # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
280
284
  def attribute_for_inspect(attr_name)
285
+ attr_name = attr_name.to_s
286
+ attr_name = self.class.attribute_aliases[attr_name] || attr_name
281
287
  value = _read_attribute(attr_name)
282
288
  format_for_inspect(value)
283
289
  end
@@ -297,8 +303,10 @@ module ActiveRecord
297
303
  # task.is_done = true
298
304
  # task.attribute_present?(:title) # => true
299
305
  # task.attribute_present?(:is_done) # => true
300
- def attribute_present?(attribute)
301
- value = _read_attribute(attribute)
306
+ def attribute_present?(attr_name)
307
+ attr_name = attr_name.to_s
308
+ attr_name = self.class.attribute_aliases[attr_name] || attr_name
309
+ value = _read_attribute(attr_name)
302
310
  !value.nil? && !(value.respond_to?(:empty?) && value.empty?)
303
311
  end
304
312
 
@@ -377,8 +385,8 @@ module ActiveRecord
377
385
  end
378
386
 
379
387
  def attributes_with_values(attribute_names)
380
- attribute_names.each_with_object({}) do |name, attrs|
381
- attrs[name] = _read_attribute(name)
388
+ attribute_names.index_with do |name|
389
+ _read_attribute(name)
382
390
  end
383
391
  end
384
392
 
@@ -386,7 +394,7 @@ module ActiveRecord
386
394
  def attributes_for_update(attribute_names)
387
395
  attribute_names &= self.class.column_names
388
396
  attribute_names.delete_if do |name|
389
- readonly_attribute?(name)
397
+ self.class.readonly_attribute?(name)
390
398
  end
391
399
  end
392
400
 
@@ -403,16 +411,12 @@ module ActiveRecord
403
411
  if value.is_a?(String) && value.length > 50
404
412
  "#{value[0, 50]}...".inspect
405
413
  elsif value.is_a?(Date) || value.is_a?(Time)
406
- %("#{value.to_s(:db)}")
414
+ %("#{value.to_s(:inspect)}")
407
415
  else
408
416
  value.inspect
409
417
  end
410
418
  end
411
419
 
412
- def readonly_attribute?(name)
413
- self.class.readonly_attributes.include?(name)
414
- end
415
-
416
420
  def pk_attribute?(name)
417
421
  name == @primary_key
418
422
  end
@@ -205,13 +205,13 @@ module ActiveRecord
205
205
  # tracking is performed. The methods +changed?+ and +changed_in_place?+
206
206
  # will be called from ActiveModel::Dirty. See the documentation for those
207
207
  # methods in ActiveModel::Type::Value for more details.
208
- def attribute(name, cast_type = Type::Value.new, **options)
208
+ def attribute(name, cast_type = nil, **options, &block)
209
209
  name = name.to_s
210
210
  reload_schema_from_cache
211
211
 
212
212
  self.attributes_to_define_after_schema_loads =
213
213
  attributes_to_define_after_schema_loads.merge(
214
- name => [cast_type, options]
214
+ name => [cast_type || block, options]
215
215
  )
216
216
  end
217
217
 
@@ -246,11 +246,7 @@ module ActiveRecord
246
246
  def load_schema! # :nodoc:
247
247
  super
248
248
  attributes_to_define_after_schema_loads.each do |name, (type, options)|
249
- if type.is_a?(Symbol)
250
- type = ActiveRecord::Type.lookup(type, **options.except(:default))
251
- end
252
-
253
- define_attribute(name, type, **options.slice(:default))
249
+ define_attribute(name, _lookup_cast_type(name, type, options), **options.slice(:default))
254
250
  end
255
251
  end
256
252
 
@@ -273,6 +269,30 @@ module ActiveRecord
273
269
  end
274
270
  _default_attributes[name] = default_attribute
275
271
  end
272
+
273
+ def decorate_attribute_type(attr_name, **default)
274
+ type, options = attributes_to_define_after_schema_loads[attr_name]
275
+
276
+ attribute(attr_name, **default) do |cast_type|
277
+ if type && !type.is_a?(Proc)
278
+ cast_type = _lookup_cast_type(attr_name, type, options)
279
+ end
280
+
281
+ yield cast_type
282
+ end
283
+ end
284
+
285
+ def _lookup_cast_type(name, type, options)
286
+ case type
287
+ when Symbol
288
+ adapter_name = ActiveRecord::Type.adapter_name_from(self)
289
+ ActiveRecord::Type.lookup(type, **options.except(:default), adapter: adapter_name)
290
+ when Proc
291
+ type[type_for_attribute(name)]
292
+ else
293
+ type || type_for_attribute(name)
294
+ end
295
+ end
276
296
  end
277
297
  end
278
298
  end
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  # Association with autosave option defines several callbacks on your
32
32
  # model (around_save, before_save, after_create, after_update). Please note that
33
33
  # callbacks are executed in the order they were defined in
34
- # model. You should avoid modifying the association content, before
34
+ # model. You should avoid modifying the association content before
35
35
  # autosave callbacks are executed. Placing your callbacks after
36
36
  # associations is usually a good practice.
37
37
  #
@@ -91,8 +91,9 @@ module ActiveRecord
91
91
  # post.save # => saves both post and comment
92
92
  #
93
93
  # post = Post.create(title: 'ruby rocks')
94
- # post.comments.create(body: 'hello world')
95
- # post.save # => saves both post and comment
94
+ # comment = post.comments.create(body: 'hello world')
95
+ # comment.body = 'hi everyone'
96
+ # post.save # => saves post, but not comment
96
97
  #
97
98
  # When <tt>:autosave</tt> is true all children are saved, no matter whether they
98
99
  # are new records or not:
@@ -102,11 +103,10 @@ module ActiveRecord
102
103
  # end
103
104
  #
104
105
  # post = Post.create(title: 'ruby rocks')
105
- # post.comments.create(body: 'hello world')
106
- # post.comments[0].body = 'hi everyone'
106
+ # comment = post.comments.create(body: 'hello world')
107
+ # comment.body = 'hi everyone'
107
108
  # post.comments.build(body: "good morning.")
108
- # post.title += "!"
109
- # post.save # => saves both post and comments.
109
+ # post.save # => saves post and both comments.
110
110
  #
111
111
  # Destroying one of the associated models as part of the parent's save action
112
112
  # is as simple as marking it for destruction:
@@ -127,6 +127,14 @@ module ActiveRecord
127
127
  # Now it _is_ removed from the database:
128
128
  #
129
129
  # Comment.find_by(id: id).nil? # => true
130
+ #
131
+ # === Caveats
132
+ #
133
+ # Note that autosave will only trigger for already-persisted association records
134
+ # if the records themselves have been changed. This is to protect against
135
+ # <tt>SystemStackError</tt> caused by circular association validations. The one
136
+ # exception is if a custom validation context is used, in which case the validations
137
+ # will always fire on the associated records.
130
138
  module AutosaveAssociation
131
139
  extend ActiveSupport::Concern
132
140
 
@@ -147,8 +155,23 @@ module ActiveRecord
147
155
 
148
156
  module ClassMethods # :nodoc:
149
157
  private
158
+ if Module.method(:method_defined?).arity == 1 # MRI 2.5 and older
159
+ using Module.new {
160
+ refine Module do
161
+ def method_defined?(method, inherit = true)
162
+ if inherit
163
+ super(method)
164
+ else
165
+ instance_methods(false).include?(method.to_sym)
166
+ end
167
+ end
168
+ end
169
+ }
170
+ end
171
+
150
172
  def define_non_cyclic_method(name, &block)
151
- return if instance_methods(false).include?(name)
173
+ return if method_defined?(name, false)
174
+
152
175
  define_method(name) do |*args|
153
176
  result = true; @_already_called ||= {}
154
177
  # Loop prevention for validation of associations
@@ -278,8 +301,9 @@ module ActiveRecord
278
301
  end
279
302
  end
280
303
 
281
- # go through nested autosave associations that are loaded in memory (without loading
282
- # any new ones), and return true if is changed for autosave
304
+ # Go through nested autosave associations that are loaded in memory (without loading
305
+ # any new ones), and return true if any are changed for autosave.
306
+ # Returns false if already called to prevent an infinite loop.
283
307
  def nested_records_changed_for_autosave?
284
308
  @_nested_records_changed_for_autosave_already_called ||= false
285
309
  return false if @_nested_records_changed_for_autosave_already_called
@@ -327,21 +351,16 @@ module ActiveRecord
327
351
  if reflection.options[:autosave]
328
352
  indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors)
329
353
 
330
- record.errors.each do |attribute, message|
354
+ record.errors.group_by_attribute.each { |attribute, errors|
331
355
  attribute = normalize_reflection_attribute(indexed_attribute, reflection, index, attribute)
332
- errors[attribute] << message
333
- errors[attribute].uniq!
334
- end
335
-
336
- record.errors.details.each_key do |attribute|
337
- reflection_attribute =
338
- normalize_reflection_attribute(indexed_attribute, reflection, index, attribute).to_sym
339
356
 
340
- record.errors.details[attribute].each do |error|
341
- errors.details[reflection_attribute] << error
342
- errors.details[reflection_attribute].uniq!
343
- end
344
- end
357
+ errors.each { |error|
358
+ self.errors.import(
359
+ error,
360
+ attribute: attribute
361
+ )
362
+ }
363
+ }
345
364
  else
346
365
  errors.add(reflection.name)
347
366
  end
@@ -438,9 +457,9 @@ module ActiveRecord
438
457
  if autosave && record.marked_for_destruction?
439
458
  record.destroy
440
459
  elsif autosave != false
441
- key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id
460
+ key = reflection.options[:primary_key] ? public_send(reflection.options[:primary_key]) : id
442
461
 
443
- if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
462
+ if (autosave && record.changed_for_autosave?) || record_changed?(reflection, record, key)
444
463
  unless reflection.through_reflection
445
464
  record[reflection.foreign_key] = key
446
465
  if inverse_reflection = reflection.inverse_of
@@ -466,7 +485,7 @@ module ActiveRecord
466
485
  def association_foreign_key_changed?(reflection, record, key)
467
486
  return false if reflection.through_reflection?
468
487
 
469
- record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key
488
+ record._has_attribute?(reflection.foreign_key) && record._read_attribute(reflection.foreign_key) != key
470
489
  end
471
490
 
472
491
  # Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
@@ -487,7 +506,7 @@ module ActiveRecord
487
506
  saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
488
507
 
489
508
  if association.updated?
490
- association_id = record.send(reflection.options[:primary_key] || :id)
509
+ association_id = record.public_send(reflection.options[:primary_key] || :id)
491
510
  self[reflection.foreign_key] = association_id
492
511
  association.loaded!
493
512
  end
@@ -502,9 +521,7 @@ module ActiveRecord
502
521
  end
503
522
 
504
523
  def _ensure_no_duplicate_errors
505
- errors.messages.each_key do |attribute|
506
- errors[attribute].uniq!
507
- end
524
+ errors.uniq!
508
525
  end
509
526
  end
510
527
  end
@@ -1,22 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "yaml"
4
3
  require "active_support/benchmarkable"
5
4
  require "active_support/dependencies"
6
5
  require "active_support/descendants_tracker"
7
6
  require "active_support/time"
8
- require "active_support/core_ext/module/attribute_accessors"
9
- require "active_support/core_ext/array/extract_options"
10
- require "active_support/core_ext/hash/deep_merge"
11
- require "active_support/core_ext/hash/slice"
12
- require "active_support/core_ext/string/behavior"
13
- require "active_support/core_ext/kernel/singleton_class"
14
- require "active_support/core_ext/module/introspection"
15
- require "active_support/core_ext/object/duplicable"
16
7
  require "active_support/core_ext/class/subclasses"
17
- require "active_record/attribute_decorators"
18
- require "active_record/define_callbacks"
19
- require "active_record/errors"
20
8
  require "active_record/log_subscriber"
21
9
  require "active_record/explain_subscriber"
22
10
  require "active_record/relation/delegation"
@@ -285,6 +273,7 @@ module ActiveRecord #:nodoc:
285
273
  extend Querying
286
274
  extend Translation
287
275
  extend DynamicMatchers
276
+ extend DelegatedType
288
277
  extend Explain
289
278
  extend Enum
290
279
  extend Delegation::DelegateCache
@@ -303,10 +292,8 @@ module ActiveRecord #:nodoc:
303
292
  include Validations
304
293
  include CounterCache
305
294
  include Attributes
306
- include AttributeDecorators
307
295
  include Locking::Optimistic
308
296
  include Locking::Pessimistic
309
- include DefineCallbacks
310
297
  include AttributeMethods
311
298
  include Callbacks
312
299
  include Timestamp
@@ -321,6 +308,7 @@ module ActiveRecord #:nodoc:
321
308
  include Serialization
322
309
  include Store
323
310
  include SecureToken
311
+ include SignedId
324
312
  include Suppressor
325
313
  end
326
314
 
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  # = Active Record \Callbacks
5
5
  #
6
6
  # \Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
7
- # before or after an alteration of the object state. This can be used to make sure that associated and
7
+ # before or after a change in the object state. This can be used to make sure that associated and
8
8
  # dependent objects are deleted when {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] is called (by overwriting +before_destroy+) or
9
9
  # to massage attributes before they're validated (by overwriting +before_validation+).
10
10
  # As an example of the callbacks initiated, consider the {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] call for a new record:
@@ -32,7 +32,7 @@ module ActiveRecord
32
32
  # is found and instantiated by a finder, with <tt>after_initialize</tt> being triggered after new objects
33
33
  # are instantiated as well.
34
34
  #
35
- # There are nineteen callbacks in total, which give you immense power to react and prepare for each state in the
35
+ # There are nineteen callbacks in total, which give a lot of control over how to react and prepare for each state in the
36
36
  # Active Record life cycle. The sequence for calling {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] for an existing record is similar,
37
37
  # except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
38
38
  #
@@ -64,7 +64,7 @@ module ActiveRecord
64
64
  #
65
65
  # Besides the overwritable callback methods, it's also possible to register callbacks through the
66
66
  # use of the callback macros. Their main advantage is that the macros add behavior into a callback
67
- # queue that is kept intact down through an inheritance hierarchy.
67
+ # queue that is kept intact through an inheritance hierarchy.
68
68
  #
69
69
  # class Topic < ActiveRecord::Base
70
70
  # before_destroy :destroy_author
@@ -74,7 +74,7 @@ module ActiveRecord
74
74
  # before_destroy :destroy_readers
75
75
  # end
76
76
  #
77
- # Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
77
+ # When <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
78
78
  # run, both +destroy_author+ and +destroy_readers+ are called.
79
79
  #
80
80
  # *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
@@ -83,10 +83,9 @@ module ActiveRecord
83
83
  #
84
84
  # == Types of callbacks
85
85
  #
86
- # There are four types of callbacks accepted by the callback macros: Method references (symbol), callback objects,
87
- # inline methods (using a proc). Method references and callback objects
88
- # are the recommended approaches, inline methods using a proc are sometimes appropriate (such as for
89
- # creating mix-ins).
86
+ # There are three types of callbacks accepted by the callback macros: method references (symbol), callback objects,
87
+ # inline methods (using a proc). Method references and callback objects are the recommended approaches,
88
+ # inline methods using a proc are sometimes appropriate (such as for creating mix-ins).
90
89
  #
91
90
  # The method reference callbacks work by specifying a protected or private method available in the object, like this:
92
91
  #
@@ -179,8 +178,8 @@ module ActiveRecord
179
178
  #
180
179
  # == Ordering callbacks
181
180
  #
182
- # Sometimes the code needs that the callbacks execute in a specific order. For example, a +before_destroy+
183
- # callback (+log_children+ in this case) should be executed before the children get destroyed by the
181
+ # Sometimes application code requires that callbacks execute in a specific order. For example, a +before_destroy+
182
+ # callback (+log_children+ in this case) should be executed before records in the +children+ association are destroyed by the
184
183
  # <tt>dependent: :destroy</tt> option.
185
184
  #
186
185
  # Let's look at the code below:
@@ -196,8 +195,8 @@ module ActiveRecord
196
195
  # end
197
196
  # end
198
197
  #
199
- # In this case, the problem is that when the +before_destroy+ callback is executed, the children are not available
200
- # because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback gets executed first.
198
+ # In this case, the problem is that when the +before_destroy+ callback is executed, records in the +children+ association no
199
+ # longer exist because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback was executed first.
201
200
  # You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
202
201
  #
203
202
  # class Topic < ActiveRecord::Base
@@ -211,7 +210,7 @@ module ActiveRecord
211
210
  # end
212
211
  # end
213
212
  #
214
- # This way, the +before_destroy+ gets executed before the <tt>dependent: :destroy</tt> is called, and the data is still available.
213
+ # This way, the +before_destroy+ is executed before the <tt>dependent: :destroy</tt> is called, and the data is still available.
215
214
  #
216
215
  # Also, there are cases when you want several callbacks of the same type to
217
216
  # be executed in order.
@@ -235,10 +234,10 @@ module ActiveRecord
235
234
  # end
236
235
  # end
237
236
  #
238
- # In this case the +log_children+ gets executed before +do_something_else+.
237
+ # In this case the +log_children+ is executed before +do_something_else+.
239
238
  # The same applies to all non-transactional callbacks.
240
239
  #
241
- # In case there are multiple transactional callbacks as seen below, the order
240
+ # As seen below, in case there are multiple transactional callbacks the order
242
241
  # is reversed.
243
242
  #
244
243
  # For example:
@@ -260,16 +259,16 @@ module ActiveRecord
260
259
  # end
261
260
  # end
262
261
  #
263
- # In this case the +do_something_else+ gets executed before +log_children+.
262
+ # In this case the +do_something_else+ is executed before +log_children+.
264
263
  #
265
264
  # == \Transactions
266
265
  #
267
266
  # The entire callback chain of a {#save}[rdoc-ref:Persistence#save], {#save!}[rdoc-ref:Persistence#save!],
268
267
  # or {#destroy}[rdoc-ref:Persistence#destroy] call runs within a transaction. That includes <tt>after_*</tt> hooks.
269
- # If everything goes fine a COMMIT is executed once the chain has been completed.
268
+ # If everything goes fine a +COMMIT+ is executed once the chain has been completed.
270
269
  #
271
- # If a <tt>before_*</tt> callback cancels the action a ROLLBACK is issued. You
272
- # can also trigger a ROLLBACK raising an exception in any of the callbacks,
270
+ # If a <tt>before_*</tt> callback cancels the action a +ROLLBACK+ is issued. You
271
+ # can also trigger a +ROLLBACK+ raising an exception in any of the callbacks,
273
272
  # including <tt>after_*</tt> hooks. Note, however, that in that case the client
274
273
  # needs to be aware of it because an ordinary {#save}[rdoc-ref:Persistence#save] will raise such exception
275
274
  # instead of quietly returning +false+.
@@ -280,17 +279,17 @@ module ActiveRecord
280
279
  # <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
281
280
  # defines what part of the chain the callback runs in.
282
281
  #
283
- # To find all callbacks in the before_save callback chain:
282
+ # To find all callbacks in the +before_save+ callback chain:
284
283
  #
285
284
  # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }
286
285
  #
287
- # Returns an array of callback objects that form the before_save chain.
286
+ # Returns an array of callback objects that form the +before_save+ chain.
288
287
  #
289
288
  # To further check if the before_save chain contains a proc defined as <tt>rest_when_dead</tt> use the <tt>filter</tt> property of the callback object:
290
289
  #
291
290
  # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)
292
291
  #
293
- # Returns true or false depending on whether the proc is contained in the before_save callback chain on a Topic model.
292
+ # Returns true or false depending on whether the proc is contained in the +before_save+ callback chain on a Topic model.
294
293
  #
295
294
  module Callbacks
296
295
  extend ActiveSupport::Concern
@@ -302,6 +301,17 @@ module ActiveRecord
302
301
  :before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
303
302
  ]
304
303
 
304
+ module ClassMethods # :nodoc:
305
+ include ActiveModel::Callbacks
306
+ end
307
+
308
+ included do
309
+ include ActiveModel::Validations::Callbacks
310
+
311
+ define_model_callbacks :initialize, :find, :touch, only: :after
312
+ define_model_callbacks :save, :create, :update, :destroy
313
+ end
314
+
305
315
  def destroy #:nodoc:
306
316
  @_destroy_callback_already_called ||= false
307
317
  return if @_destroy_callback_already_called
@@ -22,7 +22,7 @@ module ActiveRecord
22
22
 
23
23
  def load(yaml)
24
24
  return object_class.new if object_class != Object && yaml.nil?
25
- return yaml unless yaml.is_a?(String) && /^---/.match?(yaml)
25
+ return yaml unless yaml.is_a?(String) && yaml.start_with?("---")
26
26
  obj = YAML.load(yaml)
27
27
 
28
28
  assert_valid_value(obj, action: "load")