heartcombo/devise

"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!