"request" is nil within DeviseController when subclassing a Devise controller and using scoped views
Closed this issue · 5 comments
We have a Github repo reproducing this issue:
https://github.com/atasay/devise-issue
If you run the tests by running the default rake task, you will see the error we're getting.
This is the exception:
1) Error:
test_index(ErrorReproducerControllerTest):
NoMethodError: undefined method `env' for nil:NilClass
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/devise-2.0.4/app/controllers/devise_controller.rb:38:in `devise_mapping'
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/devise-2.0.4/app/controllers/devise_controller.rb:159:in `_prefixes'
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/actionpack-3.2.3/lib/abstract_controller/view_paths.rb:45:in `lookup_context'
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/actionpack-3.2.3/lib/abstract_controller/view_paths.rb:15:in `rescue in formats='
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/actionpack-3.2.3/lib/abstract_controller/view_paths.rb:13:in `formats='
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/actionpack-3.2.3/lib/action_controller/test_case.rb:442:in `process'
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/devise-2.0.4/lib/devise/test_helpers.rb:19:in `block in process'
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/devise-2.0.4/lib/devise/test_helpers.rb:71:in `catch'
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/devise-2.0.4/lib/devise/test_helpers.rb:71:in `_catch_warden'
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/devise-2.0.4/lib/devise/test_helpers.rb:19:in `process'
/Users/atasay/.rvm/gems/ruby-1.9.3-p125/gems/actionpack-3.2.3/lib/action_controller/test_case.rb:385:in `post'
/Users/atasay/Desktop/cmondevise/test/controllers/error_reproducer_controller_test.rb:13:in `test_index'
At the top of the stack trace, it says the error is coming from devise_controller.rb:38, which looks like this:
# Attempt to find the mapped route for devise based on request path
def devise_mapping
@devise_mapping ||= request.env["devise.mapping"]
end
So request
is actually nil here. And this is within DeviseController while calling post :create
.
This is the full test:
def test_index
user = User.create :email => "foo@example.com", :password => "password", :password_confirmation => "password"
sign_in user
request.env["devise.mapping"] = Devise.mappings[:user]
post :create # <------------ This is where the error occurs
assert_response :success
end
This is on Devise 2.1.0 and Rails 3.2.3 but we first noticed the issue with Devise 2.0.4.
Thanks in advance for any suggestions.
Thanks for the detailed report, we will take a look.
I should also mention that the scoped_views
config option directly causes the issue. When setting it to false, the error goes away.
I have some additional information on this bug.
I tracked it down to the order of instance variables assigned in this file, particular the order of @controller.formats= and @controller.request=
~/.rvm/gems/ruby-1.9.3-p194@global/gems/actionpack-3.2.3/lib/action_controller/test_case.rb:444:in `process'
This process() method has an assignment:
@controller.formats = nil
which ends up calling into ActionView, and eventually Devise to figure out whether to use scoped views or not (and explodes because request is undefined). Request is undefined because the line
@controller.request = @request
happens after the @controller.formats= call. Once I moved @controller.request = @request before the formats assignment, Devise no longer explodes.
In summary, it looks like in the context of functional controller tests, Devise relies on request object being setup to determine supported formats of the controller, but it can not rely on the request object yet because it wasn't assigned.
I am not clear whether it's a Devise issue, or ActionSupport issue, but it is very surprising that it hasn't gotten caught before. Basically any controller tests with scoped views with Devise would be broken.
Thanks for the detailed report. I have added a fix for Devise master, can you please check it works for you? Thanks!
Seems to be fixed! We are now getting a proper result from posting to an action. Thank you so much!