activerecord 7.2.0.beta2 → 7.2.0.beta3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -1
  3. data/lib/active_record/associations/collection_association.rb +3 -3
  4. data/lib/active_record/associations/errors.rb +265 -0
  5. data/lib/active_record/associations.rb +0 -262
  6. data/lib/active_record/attribute_methods/dirty.rb +1 -1
  7. data/lib/active_record/attribute_methods/read.rb +3 -3
  8. data/lib/active_record/attribute_methods/write.rb +3 -3
  9. data/lib/active_record/attribute_methods.rb +8 -6
  10. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +27 -11
  11. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  12. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  13. data/lib/active_record/connection_adapters/abstract/transaction.rb +67 -9
  14. data/lib/active_record/connection_adapters/abstract_adapter.rb +8 -1
  15. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1 -1
  16. data/lib/active_record/database_configurations/database_config.rb +4 -0
  17. data/lib/active_record/errors.rb +20 -8
  18. data/lib/active_record/gem_version.rb +1 -1
  19. data/lib/active_record/railtie.rb +2 -3
  20. data/lib/active_record/railties/databases.rake +1 -1
  21. data/lib/active_record/relation/calculations.rb +1 -1
  22. data/lib/active_record/relation/query_methods.rb +21 -9
  23. data/lib/active_record/signed_id.rb +9 -0
  24. data/lib/active_record/test_fixtures.rb +10 -3
  25. data/lib/active_record/timestamp.rb +1 -1
  26. data/lib/active_record/transaction.rb +56 -55
  27. data/lib/active_record/transactions.rb +1 -1
  28. data/lib/active_record.rb +1 -1
  29. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  30. metadata +13 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79dcd5171d733c47a82a63fd34a602529290fc29e1e1011906763b5a46bec471
4
- data.tar.gz: b910e80c8172f01a7aabe42b3b6fb12e11f704c7951972684d1694d136b05520
3
+ metadata.gz: 0a80eeb42f7130f9c9b8f9b9980959b202c550f1cf958326ffb3364161435b5f
4
+ data.tar.gz: b875a8e003cfce381c29733acf6c3f019ffed72a52a1f01be123913294ea31de
5
5
  SHA512:
6
- metadata.gz: 5126184906916972f44998d4180a0975a34504341702aa941b065a1eec31014e4066ce5e76a34d7270d4e58e4ab5e068806cdbb2d5bb3177552406b7ce781c84
7
- data.tar.gz: 876047d057f0103a6e255880ffe12d4625bbbc91e81df3cd1eee22e08d853740c1063a1df7883efe805f56c17abd115e9e5b0c57241d5ab1387eb5fb65214df6
6
+ metadata.gz: 0eb8b60fa9d521a514799b6e5f5a5d1adaac422270b20245849ade043cd45aa485d0a17b57d163c641bc3ae29fa5700dbfa11c55451858de0d0b1647a97a666b
7
+ data.tar.gz: 68f46c24553e6c1f85751aa223a53e186abd1ec8a744e3803709552e33bbe757193498141af13b918646bc83b1bcb83bee5a2e58f3f1278d785e54a3c444ca32
data/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ## Rails 7.2.0.beta3 (July 11, 2024) ##
2
+
3
+ * Add condensed `#inspect` for `ConnectionPool`, `AbstractAdapter`, and
4
+ `DatabaseConfig`.
5
+
6
+ *Hartley McGuire*
7
+
8
+ * Fixed a memory performance issue in Active Record attribute methods definition.
9
+
10
+ *Jean Boussier*
11
+
12
+ * Define the new Active Support notification event `start_transaction.active_record`.
13
+
14
+ This event is fired when database transactions or savepoints start, and
15
+ complements `transaction.active_record`, which is emitted when they finish.
16
+
17
+ The payload has the transaction (`:transaction`) and the connection (`:connection`).
18
+
19
+ *Xavier Noria*
20
+
21
+ * Fix an issue where the IDs reader method did not return expected results
22
+ for preloaded associations in models using composite primary keys.
23
+
24
+ *Jay Ang*
25
+
26
+
1
27
  ## Rails 7.2.0.beta2 (June 04, 2024) ##
2
28
 
3
29
  * The payload of `sql.active_record` Active Support notifications now has the current transaction in the `:transaction` key.
@@ -12,6 +38,7 @@
12
38
 
13
39
  *Xavier Noria*
14
40
 
41
+
15
42
  ## Rails 7.2.0.beta1 (May 29, 2024) ##
16
43
 
17
44
  * Fix inference of association model on nested models with the same demodularized name.
@@ -407,7 +434,7 @@
407
434
 
408
435
  *Rafael Mendonça França*
409
436
 
410
- * Remove deprecated `ActiveRecord::Migration.check_pending` method.
437
+ * Remove deprecated `ActiveRecord::Migration.check_pending!` method.
411
438
 
412
439
  *Rafael Mendonça França*
413
440
 
@@ -50,11 +50,11 @@ module ActiveRecord
50
50
  # Implements the ids reader method, e.g. foo.item_ids for Foo.has_many :items
51
51
  def ids_reader
52
52
  if loaded?
53
- target.pluck(reflection.association_primary_key)
53
+ target.pluck(*reflection.association_primary_key)
54
54
  elsif !target.empty?
55
- load_target.pluck(reflection.association_primary_key)
55
+ load_target.pluck(*reflection.association_primary_key)
56
56
  else
57
- @association_ids ||= scope.pluck(reflection.association_primary_key)
57
+ @association_ids ||= scope.pluck(*reflection.association_primary_key)
58
58
  end
59
59
  end
60
60
 
@@ -0,0 +1,265 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class AssociationNotFoundError < ConfigurationError # :nodoc:
5
+ attr_reader :record, :association_name
6
+
7
+ def initialize(record = nil, association_name = nil)
8
+ @record = record
9
+ @association_name = association_name
10
+ if record && association_name
11
+ super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?")
12
+ else
13
+ super("Association was not found.")
14
+ end
15
+ end
16
+
17
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
18
+ include DidYouMean::Correctable
19
+
20
+ def corrections
21
+ if record && association_name
22
+ @corrections ||= begin
23
+ maybe_these = record.class.reflections.keys
24
+ DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(association_name)
25
+ end
26
+ else
27
+ []
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ class InverseOfAssociationNotFoundError < ActiveRecordError # :nodoc:
34
+ attr_reader :reflection, :associated_class
35
+
36
+ def initialize(reflection = nil, associated_class = nil)
37
+ if reflection
38
+ @reflection = reflection
39
+ @associated_class = associated_class.nil? ? reflection.klass : associated_class
40
+ super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
41
+ else
42
+ super("Could not find the inverse association.")
43
+ end
44
+ end
45
+
46
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
47
+ include DidYouMean::Correctable
48
+
49
+ def corrections
50
+ if reflection && associated_class
51
+ @corrections ||= begin
52
+ maybe_these = associated_class.reflections.keys
53
+ DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:inverse_of].to_s)
54
+ end
55
+ else
56
+ []
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ class InverseOfAssociationRecursiveError < ActiveRecordError # :nodoc:
63
+ attr_reader :reflection
64
+ def initialize(reflection = nil)
65
+ if reflection
66
+ @reflection = reflection
67
+ super("Inverse association #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{reflection.class_name}) is recursive.")
68
+ else
69
+ super("Inverse association is recursive.")
70
+ end
71
+ end
72
+ end
73
+
74
+ class HasManyThroughAssociationNotFoundError < ActiveRecordError # :nodoc:
75
+ attr_reader :owner_class, :reflection
76
+
77
+ def initialize(owner_class = nil, reflection = nil)
78
+ if owner_class && reflection
79
+ @owner_class = owner_class
80
+ @reflection = reflection
81
+ super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class.name}")
82
+ else
83
+ super("Could not find the association.")
84
+ end
85
+ end
86
+
87
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
88
+ include DidYouMean::Correctable
89
+
90
+ def corrections
91
+ if owner_class && reflection
92
+ @corrections ||= begin
93
+ maybe_these = owner_class.reflections.keys
94
+ maybe_these -= [reflection.name.to_s] # remove failing reflection
95
+ DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:through].to_s)
96
+ end
97
+ else
98
+ []
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError # :nodoc:
105
+ def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
106
+ if owner_class_name && reflection && source_reflection
107
+ super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
108
+ else
109
+ super("Cannot have a has_many :through association.")
110
+ end
111
+ end
112
+ end
113
+
114
+ class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
115
+ def initialize(owner_class_name = nil, reflection = nil)
116
+ if owner_class_name && reflection
117
+ super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
118
+ else
119
+ super("Cannot have a has_many :through association.")
120
+ end
121
+ end
122
+ end
123
+
124
+ class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError # :nodoc:
125
+ def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
126
+ if owner_class_name && reflection && source_reflection
127
+ super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
128
+ else
129
+ super("Cannot have a has_many :through association.")
130
+ end
131
+ end
132
+ end
133
+
134
+ class HasOneThroughCantAssociateThroughCollection < ActiveRecordError # :nodoc:
135
+ def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
136
+ if owner_class_name && reflection && through_reflection
137
+ super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
138
+ else
139
+ super("Cannot have a has_one :through association.")
140
+ end
141
+ end
142
+ end
143
+
144
+ class HasOneAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
145
+ def initialize(owner_class_name = nil, reflection = nil)
146
+ if owner_class_name && reflection
147
+ super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
148
+ else
149
+ super("Cannot have a has_one :through association.")
150
+ end
151
+ end
152
+ end
153
+
154
+ class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError # :nodoc:
155
+ def initialize(reflection = nil)
156
+ if reflection
157
+ through_reflection = reflection.through_reflection
158
+ source_reflection_names = reflection.source_reflection_names
159
+ source_associations = reflection.through_reflection.klass._reflections.keys
160
+ super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')}?")
161
+ else
162
+ super("Could not find the source association(s).")
163
+ end
164
+ end
165
+ end
166
+
167
+ class HasManyThroughOrderError < ActiveRecordError # :nodoc:
168
+ def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
169
+ if owner_class_name && reflection && through_reflection
170
+ super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through '#{owner_class_name}##{through_reflection.name}' before the through association is defined.")
171
+ else
172
+ super("Cannot have a has_many :through association before the through association is defined.")
173
+ end
174
+ end
175
+ end
176
+
177
+ class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError # :nodoc:
178
+ def initialize(owner = nil, reflection = nil)
179
+ if owner && reflection
180
+ super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")
181
+ else
182
+ super("Cannot modify association.")
183
+ end
184
+ end
185
+ end
186
+
187
+ class CompositePrimaryKeyMismatchError < ActiveRecordError # :nodoc:
188
+ attr_reader :reflection
189
+
190
+ def initialize(reflection = nil)
191
+ if reflection
192
+ if reflection.has_one? || reflection.collection?
193
+ super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.active_record_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
194
+ else
195
+ super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.association_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
196
+ end
197
+ else
198
+ super("Association primary key doesn't match with foreign key.")
199
+ end
200
+ end
201
+ end
202
+
203
+ class AmbiguousSourceReflectionForThroughAssociation < ActiveRecordError # :nodoc:
204
+ def initialize(klass, macro, association_name, options, possible_sources)
205
+ example_options = options.dup
206
+ example_options[:source] = possible_sources.first
207
+
208
+ super("Ambiguous source reflection for through association. Please " \
209
+ "specify a :source directive on your declaration like:\n" \
210
+ "\n" \
211
+ " class #{klass} < ActiveRecord::Base\n" \
212
+ " #{macro} :#{association_name}, #{example_options}\n" \
213
+ " end"
214
+ )
215
+ end
216
+ end
217
+
218
+ class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
219
+ end
220
+
221
+ class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
222
+ end
223
+
224
+ class ThroughNestedAssociationsAreReadonly < ActiveRecordError # :nodoc:
225
+ def initialize(owner = nil, reflection = nil)
226
+ if owner && reflection
227
+ super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
228
+ else
229
+ super("Through nested associations are read-only.")
230
+ end
231
+ end
232
+ end
233
+
234
+ class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
235
+ end
236
+
237
+ class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
238
+ end
239
+
240
+ # This error is raised when trying to eager load a polymorphic association using a JOIN.
241
+ # Eager loading polymorphic associations is only possible with
242
+ # {ActiveRecord::Relation#preload}[rdoc-ref:QueryMethods#preload].
243
+ class EagerLoadPolymorphicError < ActiveRecordError
244
+ def initialize(reflection = nil)
245
+ if reflection
246
+ super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}")
247
+ else
248
+ super("Eager load polymorphic error.")
249
+ end
250
+ end
251
+ end
252
+
253
+ # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
254
+ # (has_many, has_one) when there is at least 1 child associated instance.
255
+ # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
256
+ class DeleteRestrictionError < ActiveRecordError # :nodoc:
257
+ def initialize(name = nil)
258
+ if name
259
+ super("Cannot delete record because of dependent #{name}")
260
+ else
261
+ super("Delete restriction error.")
262
+ end
263
+ end
264
+ end
265
+ end
@@ -1,268 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
- class AssociationNotFoundError < ConfigurationError # :nodoc:
5
- attr_reader :record, :association_name
6
-
7
- def initialize(record = nil, association_name = nil)
8
- @record = record
9
- @association_name = association_name
10
- if record && association_name
11
- super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?")
12
- else
13
- super("Association was not found.")
14
- end
15
- end
16
-
17
- if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
18
- include DidYouMean::Correctable
19
-
20
- def corrections
21
- if record && association_name
22
- @corrections ||= begin
23
- maybe_these = record.class.reflections.keys
24
- DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(association_name)
25
- end
26
- else
27
- []
28
- end
29
- end
30
- end
31
- end
32
-
33
- class InverseOfAssociationNotFoundError < ActiveRecordError # :nodoc:
34
- attr_reader :reflection, :associated_class
35
-
36
- def initialize(reflection = nil, associated_class = nil)
37
- if reflection
38
- @reflection = reflection
39
- @associated_class = associated_class.nil? ? reflection.klass : associated_class
40
- super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
41
- else
42
- super("Could not find the inverse association.")
43
- end
44
- end
45
-
46
- if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
47
- include DidYouMean::Correctable
48
-
49
- def corrections
50
- if reflection && associated_class
51
- @corrections ||= begin
52
- maybe_these = associated_class.reflections.keys
53
- DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:inverse_of].to_s)
54
- end
55
- else
56
- []
57
- end
58
- end
59
- end
60
- end
61
-
62
- class InverseOfAssociationRecursiveError < ActiveRecordError # :nodoc:
63
- attr_reader :reflection
64
- def initialize(reflection = nil)
65
- if reflection
66
- @reflection = reflection
67
- super("Inverse association #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{reflection.class_name}) is recursive.")
68
- else
69
- super("Inverse association is recursive.")
70
- end
71
- end
72
- end
73
-
74
- class HasManyThroughAssociationNotFoundError < ActiveRecordError # :nodoc:
75
- attr_reader :owner_class, :reflection
76
-
77
- def initialize(owner_class = nil, reflection = nil)
78
- if owner_class && reflection
79
- @owner_class = owner_class
80
- @reflection = reflection
81
- super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class.name}")
82
- else
83
- super("Could not find the association.")
84
- end
85
- end
86
-
87
- if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
88
- include DidYouMean::Correctable
89
-
90
- def corrections
91
- if owner_class && reflection
92
- @corrections ||= begin
93
- maybe_these = owner_class.reflections.keys
94
- maybe_these -= [reflection.name.to_s] # remove failing reflection
95
- DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:through].to_s)
96
- end
97
- else
98
- []
99
- end
100
- end
101
- end
102
- end
103
-
104
- class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError # :nodoc:
105
- def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
106
- if owner_class_name && reflection && source_reflection
107
- super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
108
- else
109
- super("Cannot have a has_many :through association.")
110
- end
111
- end
112
- end
113
-
114
- class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
115
- def initialize(owner_class_name = nil, reflection = nil)
116
- if owner_class_name && reflection
117
- super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
118
- else
119
- super("Cannot have a has_many :through association.")
120
- end
121
- end
122
- end
123
-
124
- class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError # :nodoc:
125
- def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
126
- if owner_class_name && reflection && source_reflection
127
- super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
128
- else
129
- super("Cannot have a has_many :through association.")
130
- end
131
- end
132
- end
133
-
134
- class HasOneThroughCantAssociateThroughCollection < ActiveRecordError # :nodoc:
135
- def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
136
- if owner_class_name && reflection && through_reflection
137
- super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
138
- else
139
- super("Cannot have a has_one :through association.")
140
- end
141
- end
142
- end
143
-
144
- class HasOneAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
145
- def initialize(owner_class_name = nil, reflection = nil)
146
- if owner_class_name && reflection
147
- super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
148
- else
149
- super("Cannot have a has_one :through association.")
150
- end
151
- end
152
- end
153
-
154
- class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError # :nodoc:
155
- def initialize(reflection = nil)
156
- if reflection
157
- through_reflection = reflection.through_reflection
158
- source_reflection_names = reflection.source_reflection_names
159
- source_associations = reflection.through_reflection.klass._reflections.keys
160
- super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')}?")
161
- else
162
- super("Could not find the source association(s).")
163
- end
164
- end
165
- end
166
-
167
- class HasManyThroughOrderError < ActiveRecordError # :nodoc:
168
- def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
169
- if owner_class_name && reflection && through_reflection
170
- super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through '#{owner_class_name}##{through_reflection.name}' before the through association is defined.")
171
- else
172
- super("Cannot have a has_many :through association before the through association is defined.")
173
- end
174
- end
175
- end
176
-
177
- class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError # :nodoc:
178
- def initialize(owner = nil, reflection = nil)
179
- if owner && reflection
180
- super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")
181
- else
182
- super("Cannot modify association.")
183
- end
184
- end
185
- end
186
-
187
- class CompositePrimaryKeyMismatchError < ActiveRecordError # :nodoc:
188
- attr_reader :reflection
189
-
190
- def initialize(reflection = nil)
191
- if reflection
192
- if reflection.has_one? || reflection.collection?
193
- super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.active_record_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
194
- else
195
- super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.association_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
196
- end
197
- else
198
- super("Association primary key doesn't match with foreign key.")
199
- end
200
- end
201
- end
202
-
203
- class AmbiguousSourceReflectionForThroughAssociation < ActiveRecordError # :nodoc:
204
- def initialize(klass, macro, association_name, options, possible_sources)
205
- example_options = options.dup
206
- example_options[:source] = possible_sources.first
207
-
208
- super("Ambiguous source reflection for through association. Please " \
209
- "specify a :source directive on your declaration like:\n" \
210
- "\n" \
211
- " class #{klass} < ActiveRecord::Base\n" \
212
- " #{macro} :#{association_name}, #{example_options}\n" \
213
- " end"
214
- )
215
- end
216
- end
217
-
218
- class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
219
- end
220
-
221
- class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
222
- end
223
-
224
- class ThroughNestedAssociationsAreReadonly < ActiveRecordError # :nodoc:
225
- def initialize(owner = nil, reflection = nil)
226
- if owner && reflection
227
- super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
228
- else
229
- super("Through nested associations are read-only.")
230
- end
231
- end
232
- end
233
-
234
- class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
235
- end
236
-
237
- class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
238
- end
239
-
240
- # This error is raised when trying to eager load a polymorphic association using a JOIN.
241
- # Eager loading polymorphic associations is only possible with
242
- # {ActiveRecord::Relation#preload}[rdoc-ref:QueryMethods#preload].
243
- class EagerLoadPolymorphicError < ActiveRecordError
244
- def initialize(reflection = nil)
245
- if reflection
246
- super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}")
247
- else
248
- super("Eager load polymorphic error.")
249
- end
250
- end
251
- end
252
-
253
- # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
254
- # (has_many, has_one) when there is at least 1 child associated instance.
255
- # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
256
- class DeleteRestrictionError < ActiveRecordError # :nodoc:
257
- def initialize(name = nil)
258
- if name
259
- super("Cannot delete record because of dependent #{name}")
260
- else
261
- super("Delete restriction error.")
262
- end
263
- end
264
- end
265
-
266
4
  # See ActiveRecord::Associations::ClassMethods for documentation.
267
5
  module Associations # :nodoc:
268
6
  extend ActiveSupport::Autoload
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  # person.name_in_database # => "Alice"
32
32
  # person.saved_change_to_name? # => true
33
33
  # person.saved_change_to_name # => ["Allison", "Alice"]
34
- # person.name_before_last_change # => "Allison"
34
+ # person.name_before_last_save # => "Allison"
35
35
  #
36
36
  # Similar to ActiveModel::Dirty, methods can be invoked as
37
37
  # +saved_change_to_name?+ or by passing an argument to the generic method
@@ -8,11 +8,11 @@ module ActiveRecord
8
8
 
9
9
  module ClassMethods # :nodoc:
10
10
  private
11
- def define_method_attribute(name, owner:)
11
+ def define_method_attribute(canonical_name, owner:, as: canonical_name)
12
12
  ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
13
- owner, name
13
+ owner, canonical_name
14
14
  ) do |temp_method_name, attr_name_expr|
15
- owner.define_cached_method(name, as: temp_method_name, namespace: :active_record) do |batch|
15
+ owner.define_cached_method(temp_method_name, as: as, namespace: :active_record) do |batch|
16
16
  batch <<
17
17
  "def #{temp_method_name}" <<
18
18
  " _read_attribute(#{attr_name_expr}) { |n| missing_attribute(n, caller) }" <<
@@ -12,11 +12,11 @@ module ActiveRecord
12
12
 
13
13
  module ClassMethods # :nodoc:
14
14
  private
15
- def define_method_attribute=(name, owner:)
15
+ def define_method_attribute=(canonical_name, owner:, as: canonical_name)
16
16
  ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
17
- owner, name, writer: true,
17
+ owner, canonical_name, writer: true,
18
18
  ) do |temp_method_name, attr_name_expr|
19
- owner.define_cached_method("#{name}=", as: temp_method_name, namespace: :active_record) do |batch|
19
+ owner.define_cached_method(temp_method_name, as: "#{as}=", namespace: :active_record) do |batch|
20
20
  batch <<
21
21
  "def #{temp_method_name}(value)" <<
22
22
  " _write_attribute(#{attr_name_expr}, value)" <<
@@ -77,6 +77,13 @@ module ActiveRecord
77
77
  # alias attributes in Active Record are lazily generated
78
78
  end
79
79
 
80
+ def generate_alias_attribute_methods(code_generator, new_name, old_name) # :nodoc:
81
+ attribute_method_patterns.each do |pattern|
82
+ alias_attribute_method_definition(code_generator, pattern, new_name, old_name)
83
+ end
84
+ attribute_method_patterns_cache.clear
85
+ end
86
+
80
87
  def alias_attribute_method_definition(code_generator, pattern, new_name, old_name)
81
88
  old_name = old_name.to_s
82
89
 
@@ -84,12 +91,7 @@ module ActiveRecord
84
91
  raise ArgumentError, "#{self.name} model aliases `#{old_name}`, but `#{old_name}` is not an attribute. " \
85
92
  "Use `alias_method :#{new_name}, :#{old_name}` or define the method manually."
86
93
  else
87
- method_name = pattern.method_name(new_name).to_s
88
- parameters = pattern.parameters
89
-
90
- define_proxy_call(code_generator, method_name, pattern.proxy_target, parameters, old_name,
91
- namespace: :proxy_alias_attribute
92
- )
94
+ define_attribute_method_pattern(pattern, old_name, owner: code_generator, as: new_name, override: true)
93
95
  end
94
96
  end
95
97