From eecc9a2022a75686e59f3cfe3d564328f3ef2ba2 Mon Sep 17 00:00:00 2001 From: Mahmoud Bakr Date: Sat, 25 Apr 2026 07:42:30 +0300 Subject: [PATCH] Handle symbol argument in find_or_initialize_with_errors The method documented required_attributes as accepting an array, but did not guard against a bare symbol being passed directly. When a symbol was given, the subsequent .each call on required_attributes raised NoMethodError and .size returned the character count of the symbol name rather than 1, so the size comparison against attributes.size always failed. Wrapping required_attributes with Array() at the entry point normalises all valid inputs (symbol, string, array) without changing behaviour for existing callers that already pass an array. Fixes #5588 --- lib/devise/models/authenticatable.rb | 1 + test/models/authenticatable_test.rb | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/lib/devise/models/authenticatable.rb b/lib/devise/models/authenticatable.rb index df964537e..f3738b1f6 100644 --- a/lib/devise/models/authenticatable.rb +++ b/lib/devise/models/authenticatable.rb @@ -275,6 +275,7 @@ def find_or_initialize_with_error_by(attribute, value, error = :invalid) #:nodoc # Find or initialize a record with group of attributes based on a list of required attributes. def find_or_initialize_with_errors(required_attributes, attributes, error = :invalid) #:nodoc: + required_attributes = Array(required_attributes) attributes.try(:permit!) attributes = attributes.to_h.with_indifferent_access .slice(*required_attributes) diff --git a/test/models/authenticatable_test.rb b/test/models/authenticatable_test.rb index 4d58b1e49..1538cf344 100644 --- a/test/models/authenticatable_test.rb +++ b/test/models/authenticatable_test.rb @@ -38,6 +38,16 @@ class AuthenticatableTest < ActiveSupport::TestCase assert user_with_error.errors.added?(:email, :invalid) end + test 'find_or_initialize_with_errors accepts a single symbol as required_attributes' do + user = User.create!(email: "example@example.com", password: "1234567") + assert_equal user, User.find_or_initialize_with_errors(:email, { email: "example@example.com" }) + end + + test 'find_or_initialize_with_errors adds error when given a single symbol and record is not found' do + user_with_error = User.find_or_initialize_with_errors(:email, { email: "example@example.com" }) + assert user_with_error.errors.added?(:email, :invalid) + end + if defined?(ActionController::Parameters) test 'does not passes an ActionController::Parameters to find_first_by_auth_conditions through find_or_initialize_with_errors' do user = create_user(email: 'example@example.com')