1
votes

When I access my page (controller action) from a browser, the page renders fine. When I try to access the page from the controller specs, it fails.

Log message of the page working from the browser:

Started GET "/listings/2" for ::1 at 2017-12-30 17:10:13 -0500
Processing by Web::ListingsController#show as HTML
  Parameters: {"id"=>"2"}
  Listing Load (0.3ms)  SELECT  "listings".* FROM "listings" WHERE "listings"."id" = $1 LIMIT 1  [["id", 2]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
  Rendered web/listings/show.html.erb within layouts/web/application (0.8ms)
Completed 200 OK in 12ms (Views: 3.5ms | ActiveRecord: 0.5ms)
source=rack-timeout id=b2c36cc7e27a8a1be766ef1d6f5d571a timeout=10000ms service=16ms state=completed

My error from the spec:

  1) Web::ListingsController when logged in GET #show assigns the requested listing as @listing
     Failure/Error: get :show, params: {id: listing.to_param}

     ActionController::UrlGenerationError:
       No route matches {:action=>"show", :controller=>"web/listings", :params=>{:id=>"158"}}

I'm pretty sure I'm missing some sort of config setting somewhere, but after a few hours of digging, i'm not seeing it. Can someone point me to what might fix this?

Relevant Routes entry:

Rails.application.routes.draw do
  resources :listings, controller: "web/listings"
end

spec/controllers/web/listings_controller_spec.rb

RSpec.describe Web::ListingsController, type: :controller do
  describe "GET #show" do
    it "assigns the requested listing as @listing" do
      listing = FactoryBot.create(:listing, user: @user)
      @puts controller.url_for(listing)
      get :show, params: {id: listing.to_param}
      expect(assigns(:listing)).to eq(listing)
    end
  end
end

and the output of that puts statement: http://test.host/listings/158

app/controllers/web/listings_controller.rb

class Web::ListingsController < ApplicationController
   def show 
      ...
   end

end

output of rake routes | grep listing

       listings GET    /listings(.:format)            web/listings#index
                 POST   /listings(.:format)            web/listings#create
     new_listing GET    /listings/new(.:format)        web/listings#new
    edit_listing GET    /listings/:id/edit(.:format)   web/listings#edit
         listing GET    /listings/:id(.:format)        web/listings#show
                 PATCH  /listings/:id(.:format)        web/listings#update
                 PUT    /listings/:id(.:format)        web/listings#update
                 DELETE /listings/:id(.:format)        web/listings#destroy
       user_root GET    /user_root(.:format)           web/listings#index

Model is not in the web sub-dir: app/models/listing.rb

rails 4.2.10 rspec 3.5.0

2

2 Answers

2
votes

Nesting routes and nesting controllers are not the same thing. Assuming you do want a URL like 'web/listings' try:

Rails.application.routes.draw do
  namespace :web do
    resources :listings
  end
end

If you don't really want/need to namespace the route then try the named helper, eg. get listing_path(listing)

0
votes

The problem is in the spec, specifically how the params are passed.

RSpec.describe Web::ListingsController, type: :controller do
  describe "GET #show" do
    it "assigns the requested listing as @listing" do
      listing = FactoryBot.create(:listing, user: @user)
      get :show, {id: listing.to_param}
      expect(assigns(:listing)).to eq(listing)
    end
  end
end 

Do not include the params: bit. This code came from the scaffold generator :/