[Fix #49874] `has_secure_token` calls the setter method on initialize

Follow-up to #49146

The original behavior of `has_secure_token` was to use the
`send("#{attribute}=", some_value)` method so that the setter method, if
defined, was called. PR #49146 replaced the `send` method with
`write_attribute` which doesn't call the setter method and breaks
existing applications.
This commit is contained in:
abeidahmed 2023-12-03 14:10:51 +04:00
parent 6908a66c50
commit c8caf6d867
3 changed files with 23 additions and 1 deletions

View File

@ -1,3 +1,7 @@
* Fix `has_secure_token` calls the setter method on initialize.
*Abeid Ahmed*
* When using a `DATABASE_URL`, allow for a configuration to map the protocol in the URL to a specific database
adapter. This allows decoupling the adapter the application chooses to use from the database connection details
set in the deployment environment.

View File

@ -53,7 +53,7 @@ module ActiveRecord
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token(length: length) }
set_callback on, on == :initialize ? :after : :before do
if new_record? && !query_attribute(attribute)
write_attribute(attribute, self.class.generate_unique_secure_token(length: length))
send("#{attribute}=", self.class.generate_unique_secure_token(length: length))
end
end
end

View File

@ -98,4 +98,22 @@ class SecureTokenTest < ActiveRecord::TestCase
assert_predicate user.token, :present?
end
def test_token_calls_the_setter_method
model = Class.new(ActiveRecord::Base) do
self.table_name = "users"
has_secure_token on: :initialize
attr_accessor :modified_token
def token=(value)
super
self.modified_token = "#{value}_modified"
end
end
user = model.new
assert_equal "#{user.token}_modified", user.modified_token
end
end