Skip to content

Commit

Permalink
Generate secure token only once regardless of on: :initialize or `o…
Browse files Browse the repository at this point in the history
…n: :create`

Follow-up to rails#47420.

Whereas the original behavior (`on: :create`) is invoked only once
before a record is persisted, the new behavior (`on: :initialize`) is
invoked not only new record but also persisted records.

It should be invoked only once for new record consistently.
  • Loading branch information
kamipo committed Sep 5, 2023
1 parent 2fbb25b commit 2df70dd
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 1 deletion.
4 changes: 3 additions & 1 deletion activerecord/lib/active_record/secure_token.rb
Expand Up @@ -52,7 +52,9 @@ def has_secure_token(attribute = :token, length: MINIMUM_TOKEN_LENGTH, on: Activ
require "active_support/core_ext/securerandom"
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token(length: length) }
set_callback on, on == :initialize ? :after : :before do
send("#{attribute}=", self.class.generate_unique_secure_token(length: length)) if has_attribute?(attribute) && !send("#{attribute}?")
if new_record? && !query_attribute(attribute)
write_attribute(attribute, self.class.generate_unique_secure_token(length: length))
end
end
end

Expand Down
16 changes: 16 additions & 0 deletions activerecord/test/cases/secure_token_test.rb
Expand Up @@ -25,6 +25,22 @@ def test_generating_token_on_initialize_does_not_affect_reading_from_the_column
assert_equal token, User.find(@user.id).token
end

def test_generating_token_on_initialize_happens_only_once
model = Class.new(ActiveRecord::Base) do
self.table_name = "users"
has_secure_token on: :initialize
end

token = " "

user = model.new
user.update!(token: token)

assert_equal token, user.token
assert_equal token, user.reload.token
assert_equal token, model.find(user.id).token
end

def test_generating_token_on_initialize_is_skipped_if_column_was_not_selected
model = Class.new(ActiveRecord::Base) do
self.table_name = "users"
Expand Down

0 comments on commit 2df70dd

Please sign in to comment.