#url_for couldn't find route from view

119 views
Skip to first unread message

Tenzin Chemi

unread,
Jan 29, 2016, 3:11:34 AM1/29/16
to rspec

 I am getting no route matches error when I test a view which uses #url_for. My application runs fine when I load the view but rspec tests can't find the route. I don't want to mock #url_for. 

Is there a way to make this work without mocking? Thanks in advance.



1) shared/menu when auth is disabled displays 
     
Failure/Error: render template: 'shared/_menu'

    ActionView::Template::Error:

      No route matches {:action=>"index", :controller=>"gadgets"}

    # /Users/tc/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/journey/formatter.rb:46:in `generate'

    # /Users/tc/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/routing/route_set.rb:729:in `generate'

    # /Users/tc/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/routing/route_set.rb:760:in `generate'

    # /Users/tc/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/routing/route_set.rb:803:in `url_for'

    # /Users/tc/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/routing/url_for.rb:156:in `url_for'

    # /Users/tc/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/routing_url_for.rb:94:in `url_for'

Jon Rowe

unread,
Jan 30, 2016, 7:09:32 PM1/30/16
to rs...@googlegroups.com
Without seeing your routes file it’s hard to guess what’s going wrong here, the common scenarios for this involve not giving rspec required parts of the route, (for example params for any scoping you’ve applied to the route, e.g. if the route is company/:id/gadgets you need to provide the company id into the params) that would be present in the view by default

Jon Rowe
---------------------------

--
You received this message because you are subscribed to the Google Groups "rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rspec+un...@googlegroups.com.
To post to this group, send email to rs...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rspec/884080c5-7dc2-4e89-b3d8-7dfa7916a586%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tenzin Chemi

unread,
Feb 1, 2016, 11:12:03 AM2/1/16
to rspec
I have a nested resources in my route, is it because of that?

  resources :users, only: [:index, :show] do
    resources :gadgets, only: [:index, :show]
  end

Jon Rowe

unread,
Feb 1, 2016, 5:55:12 PM2/1/16
to rs...@googlegroups.com
Yes, you need to provide `:user_id` in your params for the route to match. You can see this by running `rake routes` which will show you the parameters required for each route.

Jon Rowe
---------------------------

Tenzin Chemi

unread,
Feb 1, 2016, 10:15:20 PM2/1/16
to rspec
I have a helper used for views which calls url_for(controller: 'controller_name', action: :index) and my rake route for the controller looks like this:

              Prefix Verb URI Pattern                                     Controller#Action


user_gadgets GET  /users/:user_id/gadgets(.:format)     gadgets#index


 user_gadget GET  /users/:user_id/gadgets/:id(.:format) gadgets#show


I provided the both id and user_id in params by method stub:
allow(view).to receive(:params).and_return(user_id: 'test-id', id: 'id_1')

But it still throws the same error. Thanks :)

Jon Rowe

unread,
Feb 2, 2016, 12:01:44 AM2/2/16
to rs...@googlegroups.com
Thats not the way to specify params, can you share your helper code and spec?

Jon Rowe
---------------------------

Tenzin Chemi

unread,
Feb 2, 2016, 3:16:54 AM2/2/16
to rspec
Inside Helper:
      navs << {
        active: true
        text: 'View',
        href: url_for(controller: 'gadgets, action: :index),
      }

View Spec:
require 'spec_helper'

RSpec.describe '/shared/nav', type: :view do


  before do
    allow(view).to receive(:params).and_return(user_id: 'test-id', id: 'id_1')
    render template: 'shared/_menu'
  end

  context 'when set' do
    it 'works' do
    end
  end
end

Tenzin Chemi

unread,
Feb 2, 2016, 3:18:32 AM2/2/16
to rspec
Please ignore the typo made in previous reply: 
      navs << {
       active: true
       text: 'View',
       href: url_for(controller: 'gadgets', action: :index),
     }

Jon Rowe

unread,
Feb 2, 2016, 3:35:26 AM2/2/16
to rs...@googlegroups.com
You need to add the relevant `:user_id` to the `url_for` call. e.g.

`url_for(controller: 'gadgets', action: :index, user_id: params[:user_id])`

But it would be better to use `user_gadgets_path(user_id: params[:user_id])` (note you don’t need to use params to pass this in, it could be any source of User (e.g `current_user.id` if you’re using Devise)).

Jon Rowe
---------------------------

Tenzin Chemi

unread,
Feb 2, 2016, 10:05:29 AM2/2/16
to rspec
Hi Jon Rowe, 
This `url_for(controller: 'gadgets', action: :index, user_id: params[:user_id])` worked in my tests.

Can you please explain why it rendered the correct path when I did not provide user_id inside #url_for? Does the method #url_for assumes user_id exist in params hash and it will use that by default?

Thanks!
Chemi

Jon Rowe

unread,
Feb 2, 2016, 6:33:43 PM2/2/16
to rs...@googlegroups.com
I’m afraid I can’t, it shouldn’t have worked at all without used_id being specified properly

Jon Rowe
---------------------------

Tenzin Chemi

unread,
Feb 4, 2016, 5:24:44 AM2/4/16
to rspec
Hi Jon Rowe,

I saw this in rails doc: Controllers passed in using the :controller option will retain their namespace unless it is an absolute one. I think user_id is taken from the previous url and then when I went to check gadgets it retained the user_id and formed the routes with the existing url. What do you think Jon?
Reply all
Reply to author
Forward
0 new messages