activerecord 7.2.0.beta2 → 7.2.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
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