Skip to content
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
* enhancements
* Add Rails 8 support.
- Routes are lazy-loaded by default in test and development environments now so Devise loads them before `Devise.mappings` call. [#5728](https://github.com/heartcombo/devise/pull/5728)
* New apps using Rack 3.1+ will be generated using `config.responder.error_status = :unprocessable_content`, since [`:unprocessable_entity` has been deprecated by Rack](https://github.com/rack/rack/pull/2137).

Latest versions of [Rails transparently convert `:unprocessable_entity` -> `:unprocessable_content`](https://github.com/rails/rails/pull/53383), and Devise will use that in the failure app to avoid Rack deprecation warnings for apps that are configured with `:unprocessable_entity`. They can also simply change their `error_status` to `:unprocessable_content` in latest Rack versions to avoid the warning.
* Add Ruby 3.4 and 4.0 support.
* Reenable Mongoid test suite across all Rails 7+ versions, to ensure we continue supporting it. Changes to dirty tracking to support Mongoid 8.0+. [#5568](https://github.com/heartcombo/devise/pull/5568)
* Password length validator is changed from
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,8 @@ Devise.setup do |config|
# apps is `200 OK` and `302 Found` respectively, but new apps are generated with
# these new defaults that match Hotwire/Turbo behavior.
# Note: These might become the new default in future versions of Devise.
config.responder.error_status = :unprocessable_entity
config.responder.error_status = :unprocessable_content # for Rack 3.1 or higher
# config.responder.error_status = :unprocessable_entity # for Rack 3.0 or lower

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

config.responder.redirect_status = :see_other
end
```
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/devise/confirmations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def show
set_flash_message!(:notice, :confirmed)
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
# TODO: use `error_status` when the default changes to `:unprocessable_entity`.
# TODO: use `error_status` when the default changes to `:unprocessable_entity` / `:unprocessable_content`.
respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/devise/unlocks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def show
set_flash_message! :notice, :unlocked
respond_with_navigational(resource){ redirect_to after_unlock_path_for(resource) }
else
# TODO: use `error_status` when the default changes to `:unprocessable_entity`.
# TODO: use `error_status` when the default changes to `:unprocessable_entity` / `:unprocessable_content`.
respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
end
end
Expand Down
6 changes: 3 additions & 3 deletions lib/devise/failure_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ def recall

flash.now[:alert] = i18n_message(:invalid) if is_flashing_format?
self.response = recall_app(warden_options[:recall]).call(request.env).tap { |response|
response[0] = Rack::Utils.status_code(
response[0].in?(300..399) ? Devise.responder.redirect_status : Devise.responder.error_status
)
status = response[0].in?(300..399) ? Devise.responder.redirect_status : Devise.responder.error_status
# Avoid warnings translating status to code using Rails if available (e.g. `unprocessable_entity` => `unprocessable_content`)
response[0] = ActionDispatch::Response.try(:rack_status_code, status) || Rack::Utils.status_code(status)
}
end

Expand Down
2 changes: 1 addition & 1 deletion lib/generators/templates/devise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@
# apps is `200 OK` and `302 Found` respectively, but new apps are generated with
# these new defaults that match Hotwire/Turbo behavior.
# Note: These might become the new default in future versions of Devise.
config.responder.error_status = :unprocessable_entity
config.responder.error_status = <%= Rack::Utils::SYMBOL_TO_STATUS_CODE.key(422).inspect %>
config.responder.redirect_status = :see_other

# ==> Configuration for :registerable
Expand Down
1 change: 0 additions & 1 deletion test/generators/devise_generator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,4 @@ def copy_routes
FileUtils.mkdir_p(destination)
FileUtils.cp routes, destination
end

end
8 changes: 8 additions & 0 deletions test/generators/install_generator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@ class InstallGeneratorTest < Rails::Generators::TestCase
assert_no_file "config/initializers/devise.rb"
assert_no_file "config/locales/devise.en.yml"
end

test "responder error_status based on rack version" do
run_generator(["--orm=active_record"])

error_status = Rack::RELEASE >= "3.1" ? :unprocessable_content : :unprocessable_entity

assert_file "config/initializers/devise.rb", /config\.responder\.error_status = #{error_status.inspect}/
end
end