I keep running across this error for a GET request to show action.
1) ShopController GET 'show' should be successful
Failure/Error: get 'show', :id=>#shop.user.nickname
ActionController::RoutingError:
No route matches {:id=>"picardo", :controller=>"shop", :action=>"show"}
# ./spec/controllers/shop_controller_spec.rb:8:in `block (3 levels) in <top (required)>'
My routes look like this.
#routes.rb
resources :shop, :only=>[:show]
This is the controller spec:
#shop_controller_spec.rb
before(:each) do
#shop = Fabricate(:shop)
end
describe "GET 'show'" do
it "should be successful" do
get 'show', :id=>#shop.user.nickname
response.should be_success
end
end
And teh controller:
def show
#user = User.find(:first,:conditions=>{:nickname=>params[:id]})
#shop = #user.shop
end
You have to follow some rails rules.
If you have a singular resource you have to write resource :shop and if you have the plural resources you have to write resources :shops. You can run rake routes command to see the difference.
You wrote resources :shop and request sends to ShopController that is not exist in your application because I am sure that controller named ShopsController. Because the another rails rule is to name controllers in plural form and models in singular.
Or just write a controller name in routes: resources :shop, :controller => 'shops'
Related
I am trying to test my polymorphic comments create action but I always get no route matches error in rspec.
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
#comment = #commentable.comments.new(comment_params)
#comment.user_id = current_user.id
#comment.save
redirect_to :back, notice: "Your comment was successfully posted."
end
private
def comment_params
params.require(:comment).permit(:body)
end
end
Rspec
describe "POST #create" do
context "with valid attributes" do
before do
#project = FactoryGirl.create(:project)
#comment_attr = FactoryGirl.build(:comment).attributes
end
it "creates a new comment" do
expect{
post :create, params: { project_id: #project, comment: #comment_attr }
}.to change(Comment, :count).by(1)
end
end
end
I am using this approach for testing create action in my another controllers and there is everything good, but here from some reason is throws error. I think my error is in line where I pass params to post create action but I do not see error.
UPDATE
resources :projects do
resources :comments, module: :projects
resources :tasks do
resources :comments, module: :tasks
end
end
UPDATE 2
Failure/Error: post :create, params: { project_id: #project,
commentable: #project, comment: #comment_attr }
ActionController::UrlGenerationError:
No route matches {:action=>"create", :comment=>{"id"=>nil, "commentable_type"=>nil, "commentable_id"=>nil, "user_id"=>nil,
"body"=>"MyText", "created_at"=>nil, "updated_at"=>nil,
"attachment"=>nil}, :commentable=>#, :controller=>"comments", :project_id=>#}
I think that your controller namespace does not match the routes you define. The controller is defined to not be nested (CommentsController) whereas the corresponding routes are nested and inside a module projects as well. Nesting the routes will have no influence on the controller ActionDispatch is looking for. But defining a module for the route will lead to rails expecting a controller inside the module namespace. In your case that would be Projects::CommentsController and Tasks::CommentsController. Please see "2.6 Controller Namespaces and Routing" of "Rails Routing from the Outside In" for further details.
I added your routes to a brand new rails project and ran rails routes. The output is:
Prefix Verb URI Pattern Controller#Action
project_comments GET /projects/:project_id/comments(.:format) projects/comments#index
POST /projects/:project_id/comments(.:format) projects/comments#create
...
You can therefor either remove the module definition from your routes
resources :projects do
resources :comments
resources :tasks do
resources :comments
end
end
or nest the controllers inside in a project/task namespace. Given that you want polymorphism for your comments, I would advise using the first option.
I'm getting the following error in RSpec when running my schools_controller_spec.rb test:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"schools"}
What's puzzling me is that I have the routes configured, and the action defined in the appropriate controller. I'm not getting this error for other tests in the spec, such as 'GET #index', etc. Running Rails 4.2 with RSpec/Capybara.
Here's the routes.rb:
Rails.application.routes.draw do
root to: 'pages#home', id: 'home'
resources :users
resources :schools
resource :session, only: [:new, :create, :destroy]
match '/home', to: 'pages#home', via: 'get', as: 'home_page'
end
rake routes returns:
schools GET /schools(.:format) schools#index
POST /schools(.:format) schools#create
new_school GET /schools/new(.:format) schools#new
edit_school GET /schools/:id/edit(.:format) schools#edit
school GET /schools/:id(.:format) schools#show
PATCH /schools/:id(.:format) schools#update
PUT /schools/:id(.:format) schools#update
DELETE /schools/:id(.:format) schools#destroy
There's the route defined on the fifth line, as schools#show.
The schools_controller.rb:
class SchoolsController < ApplicationController
before_action :require_signin
before_filter :admin_only, except: :index, :show
def index
#schools = School.all
end
def show
# code pending
end
private
def admin_only
unless current_user.admin?
redirect_to :back, alert: "Access denied."
end
end
end
The link to the individual school seems to be properly defined in the view helper (_school.html.haml):
%li#schools
= link_to school.name, school
= school.short_name
= school.city
= school.state
and looking at the front-end HTML confirms it's working correctly. I can see, for example: Community College of the Air Force. When I click that link the page shows the following in the debug dump:
--- !ruby/hash:ActionController::Parameters
controller: schools
action: show
id: '1'
Finally, for good measure, here's the spec file (schools_controller_spec.rb):
require 'rails_helper'
describe SchoolsController, type: :controller do
# specs omitted for other actions
describe 'GET #show' do
context "when not signed in" do
it "returns a 302 redirect code" do
get :show
expect(response.status).to eq 302
end
it "redirects to the signin page" do
get :show
expect(response).to redirect_to new_session_path
end
end
context "when signed in as user" do
before :each do
#user = double(:user)
allow(controller).to receive(:current_user).and_return #user
#school = create(:school)
end
it "assigns the school to the #school variable" do
get :show
expect(assigns(:school)).to eq #school
end
end
end
end
The route appears in rake routes. The method is defined in the appropriate controller. There don't appear to be any silly naming errors (e.g. plural/singular). The spec doesn't appear to have any issues routing GET #index or other routes for example. Everything works exactly as expected in the browser.
So why do I keep getting the "no route matches" error when I run my controller spec?
This is because the show action is expecting an id which you currently aren't passing. Replace:
get :show
With this:
get :show, id: school.id
The above assumes you have a school variable, perhaps a let in a before block?
let(:school) { create(:school) }
I am attempting to create a route to a controller method, in order that it pass an rpsec condition. For some reason that escapes me, RSPEC will not accept the route.
Here is the rspec:
describe BooksController do
describe 'searching AMZN' do
it 'should call the model method that performs AMZN search' do
post :search_tmdb, {:search_terms => 'hardware'}
end
My routes file reads:
Rottenpotatoes::Application.routes.draw do
resources :books
post '/books/search_amzn'
# map '/' to be a redirect to '/books'
root :to => redirect('/books')
end
The controller action in books_controller.rb:
def search_amzn
#books = Books.find_in_amzn(params[:search_terms])
end
I am clearly making an error in my route for I can't get away from this error message:
1) MoviesController searching AMZN should call the model method that performs AMZN search
Failure/Error: post :search_amzn, {:search_terms => 'hardware'}
ActionController::RoutingError:
No route matches {:search_terms=>"hardware", :controller=>"books", :action=>"search_amzn"}
# ./spec/controllers/books_controller_spec.rb:9:in `block (3 levels) in <top (required)>'
Here are links to the complete files:
Routes.rb: http://pastebin.com/yKBeLLnY
Spec: http://pastebin.com/cU3nRSvE
Change this:
post :search_tmdb, {:search_terms => 'hardware'}
to:
get :search_tmdb, {:search_terms => 'hardware'}
Also, in your routes file, change this:
post '/books/search_amzn'
to:
post '/books/search_amzn', as: :search_tmdb
I'm building a Rails engine under Rails 3.0.12, but I'm having issues with routes when trying to write specs for my engine's controller.
The context
I've been following an Enginex layout. The engine is named Featuring and is not isolated. It does not declare routes by itself: there is no featuring/config/routes.rb file. Instead, a routes_for_feature method is provided for the main application to define engine-specific routes.
##
# featuring/lib/featuring/rails.rb
#
require 'featuring/rails/routing'
module Featuring
class Engine < ::Rails::Engine
end
end
##
# featuring/lib/featuring/rails/routing.rb
#
module ActionDispatch::Routing
class Mapper
def routes_for_feature(feature_name)
resource_name = feature_name.to_s.pluralize.to_sym
resources resource_name, :controller => "featuring/features", :only => [:index, :show], :feature => feature_name.to_s
end
end
end
Following the Enginex template, I have a Dummy app which define the routes as so:
# featuring/spec/dummy/config/routes.rb
Dummy::Application.routes.draw do
routes_for_feature :feature_model
end
The issue
Everything is working fine when I run the rails server for the Dummy app. I can browse to http://localhost:3000/feature_models and the request is successful.
I would like to spec my Featuring::FeaturesController, but I can't get it to find the routes.
Here is the spec:
# featuring/spec/controllers/features_controller_spec.rb
require 'spec_helper'
describe Featuring::FeaturesController do
context "feature_models" do
it "GET index should be successful" do
puts Rails.application.routes.routes
get :index, { :use_route => "featuring", :feature => "feature_models" }
response.should be_success
end
end
end
And here is the result of running this spec:
rspec spec/controllers/features_controller_spec.rb:7
Featuring::FeaturesController
feature_models
GET /feature_models(.:format) {:action=>"index", :controller=>"featuring/features"}
GET /feature_models/:id(.:format) {:action=>"show", :controller=>"featuring/features"}
GET index should be successful (FAILED - 1)
Failures:
1) Featuring::FeaturesController feature_models GET index should be successful
Failure/Error: get :index, { :use_route => "featuring", :feature => "feature_models" }
ActionController::RoutingError:
No route matches {:feature=>"feature_models", :controller=>"featuring/features"}
# ./spec/controllers/features_controller_spec.rb:8:in `block (3 levels) in <top (required)>'
As you can see, even if the routes are correctly defined, the spec'ed controller seems not to find them.
Something surprises me in the RoutingError: No route matches {:feature=>"feature_models", :controller=>"featuring/features"}. The action => "index" is not displayed.
I had a similar error, and I was also confused by the lack of {:action => "index"} in the route options. However, this turned out not to be the problem. ActionDispatch treats the lack of an :action as equivalent to {:action => "index"}. See:
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/route_set.rb#L545
You may be missing a request parameter in your spec, as was the case with me. Check the Parameters line in your server log when you load the page in the browser.
The trick is to add routes { } to your spec, like so:
describe Featuring::FeaturesController do
routes { Featuring::Engine.routes }
# ...
end
See also No Route Matches ... Rails Engine
I created a controller called PolicyController and nested its route like this:
scope "/your"
resources :shops do
resources :policies
end
end
Now when I'm trying to test this controller I keep getting this error:
1) PoliciesController POST 'create' should be successful
Failure/Error: post 'create'
ActionController::RoutingError:
No route matches {:controller=>"policies", :action=>"create"}
# ./spec/controllers/policies_controller_spec.rb:7:in `block (3 levels) in <top (required)>'
Not sure how to set it right. Would appreciate the help.
Edit: Forgot my specs:
describe PoliciesController do
describe "POST 'create'" do
it "should be successful" do
post 'create'
response.should be_success
end
end
Do you think this will work?
post :create, :shop_id => 1
Definitely want to create a new shop in a before block.