devise_invitable
devise_invitable copied to clipboard
undefined method `empty?' for <User> when inviting user who already accepted invitation
When i use the invitation form to invite an user by email who has already accepted the invitation and set his password, i get the following error upon invite form submission.
NoMethodError in Users::InvitationsController#create
undefined method `empty?' for #<User id: 16, ...>
The error stack shows:
activemodel (7.0.3) lib/active_model/attribute_methods.rb:458:in `method_missing'
20:48:13 web.1 | rack (2.2.3.1) lib/rack/etag.rb:69:in `block in digest_body'
20:48:13 web.1 | actionpack (7.0.3) lib/action_dispatch/http/response.rb:146:in `each'
20:48:13 web.1 | actionpack (7.0.3) lib/action_dispatch/http/response.rb:146:in `each_chunk'
20:48:13 web.1 | actionpack (7.0.3) lib/action_dispatch/http/response.rb:128:in `each'
20:48:13 web.1 | actionpack (7.0.3) lib/action_dispatch/http/response.rb:76:in `each'
20:48:13 web.1 | actionpack (7.0.3) lib/action_dispatch/http/response.rb:481:in `each'
...
I would expect a validation to be in place and fail because the email already belongs to an active user.
My InvitationsController looks like this:
class Users::InvitationsController < Devise::InvitationsController
before_action :configure_permitted_parameters
def after_invite_path_for(resource)
users_path
end
protected
# Permit the new params here.
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:invite, keys: [:first_name, :last_name, :role])
end
end
Can you remove backtrace silencers, please? I can't see where is calling empty? on User record. The only lines calling a method empty? are invitable.errors.empty? or resource.errors.empty?
Having the same issue.
Looks like it is somewhere behind invitable in Rails 7
[activemodel (7.0.4) lib/active_model/attribute_methods.rb:458:in `method_missing']
[rack (2.2.4) lib/rack/etag.rb:71:in `block in digest_body']
[actionpack (7.0.4) lib/action_dispatch/http/response.rb:145:in `each']
[actionpack (7.0.4) lib/action_dispatch/http/response.rb:145:in `each_chunk']
[actionpack (7.0.4) lib/action_dispatch/http/response.rb:127:in `each']
[actionpack (7.0.4) lib/action_dispatch/http/response.rb:75:in `each']
[actionpack (7.0.4) lib/action_dispatch/http/response.rb:480:in `each']
[rack (2.2.4) lib/rack/body_proxy.rb:41:in `method_missing']
[rack (2.2.4) lib/rack/etag.rb:69:in `digest_body']
[rack (2.2.4) lib/rack/etag.rb:33:in `call']
[newrelic_rpm (8.10.1) lib/new_relic/agent/instrumentation/middleware_tracing.rb:100:in `call']
[rack (2.2.4) lib/rack/conditional_get.rb:40:in `call']
[newrelic_rpm (8.10.1) lib/new_relic/agent/instrumentation/middleware_tracing.rb:100:in `call']
[rack (2.2.4) lib/rack/head.rb:12:in `call']
It may be simliar to this issue: https://github.com/rack/rack/issues/1725
According to the answer, something is returning the user in the body array which rack gets on line 27: https://github.com/rack/rack/blob/v2.2.5/lib/rack/etag.rb#L27
DeviseInvitable is using respond_with resource, as devise does. Do you have the same issue with registration or sign in for example?
respond_with is a method from responders gem, what's the version of responders gem? is it the latest version?
I just disable the turbo in the form, adding data: { turbo: false }:
= simple_form_for(resource, as: resource_name, url: invitation_path(resource_name), html: { method: :post }, data: { turbo: false }) do |f|
I wasn't using the devise_invitable gem but was having the same problem. I had configured the devise parent_controller to be this class:
module Users
class DeviseController < ApplicationController
class Responder < ActionController::Responder
def to_turbo_stream
controller.render(options.merge(formats: :html))
rescue ActionView::MissingTemplate => e
raise e if get?
if has_errors? && default_action
render rendering_options.merge(formats: :html, status: :unprocessable_entity)
else
redirect_to navigation_location
end
end
end
self.responder = Responder
respond_to :html, :turbo_stream
end
end
The problem was solved by deleting this controller and switching the devise parent_controller back to the ApplicationController
After "bundle update" today, I had exactly the same issue. Thank you @fedegl, that really helped me, saved a lot of time and got my code back running. I thought I was going crazy for a moment. Thanks a lot.
Closing as it may be caused by custom code. @fedegl thanks for helping with the fix
Thanks @fedegl. My experience was similar and I had followed @excid3's tutorial on GoRails to make Devise compatible with Turbo.
This included adding a TurboFailureApp adding a TurboController and adding turbo_stream to the array of respond_to formats. It then set the parent_controller to TurboController.
I removed all that boilerplate from the GoRails fix then followed your suggestion to switch config.parent_controller = 'TurboController' back to ApplicationController. I am back on the road again.
This all happened because I updated ruby to 3.2.1 and did a big bundle update / deleted my Gemfile.lock and re-bundled. Likely getting this commit of devise which made Devise compatible with rails Turbo.
Devise is compatible with Turbo out of the box now, so none of those patches are required anymore.