Rails bug with assert_redirected_to causing NoMethodError: undefined method `first’

I’m posting about a bug I ran into recently in Rails.  It’s filed against the core team and being addressed, and documented on the forums, so this post might be unnecessary.  But the bug is bizarre and confusing enough that I thought I’d post a succinct summary of the problem and how to fix it.

If you have code in a controller that redirects to another page, say like this:

  def index    redirect_to :controller => :store  # WRONG!  end

This looks fine and actually runs fine too.  But there’s a problem if you try to test it — the tests will fail.  Consider this simple test case:

  def test_index    get :index    assert_response :redirect    assert_redirected_to :controller => 'store'  end

This test will fail with this unhelpful error message:

  1) Error:test_index(WidgetsControllerTest):NoMethodError: undefined method `first' for :store:Symbol    /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/assertions/response_assertions.rb:72:in `assert_redirected_to'    /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/assertions/response_assertions.rb:43:in `each'    /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/assertions/response_assertions.rb:43:in `assert_redirected_to'    /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/assertions.rb:60:in `clean_backtrace'    /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/assertions/response_assertions.rb:35:in `assert_redirected_to'    ./test/functional/widgets_controller_test.rb:21:in `test_index'

The problem is in that controller code.  Apparently (this was news to me) Ruby strings and symbols aren’t the same.  That is :store and ’store’ compile to different code.  If you change your controller to this:

  def index    # redirect_to :controller => :store  # WRONG!
    redirect_to :controller => 'store'   # Correct
  end

Not only will the code function properly, but it will pass the functional test too.  Hope this helps.

Leave a Reply