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.
Related
I have defined a singular resource in my routes.rb which looks like this
Rails.application.routes.draw do
resource :dog, only: [:create], to: "dog#create", controller: "dog"
end
After that I've defined a controller with a create action like this
class DogController < ApplicationController
def create
render json: {}, status: :ok
end
end
And now I'm trying to test it out with RSpec like this
require "rails_helper"
describe DogController do
it "works" do
post :create, params: { foo: :bar }
end
end
This is throwing this error instead of passing:
ActionController::UrlGenerationError:
No route matches {:action=>"create", :controller=>"dog", :foo=>:bar}
What am I doing wrong?
Change your route to
resource :dog, only: [:create], :controller => "dog"
It is better to use plural controllers even if its a singular resource
http://edgeguides.rubyonrails.org/routing.html#singular-resources
Your create action is not taking in any parameter. It's just rendering json and returning a status code
I'm getting an ActionController::UrlGenerationError: No route matches (:action => "edit", :controller => "goals") error, when I'm trying to test the goals controller
Here is my goals_controller_test.rb
require 'test_helper'
class GoalsControllerTest < ActionController::TestCase
test "should be redirected when not logged in" do
get :new
assert_response :redirect
assert_redirected_to new_user_session_path
end
test "should render the new page when logged in" do
sign_in users(:guillermo)
get :new
assert_response :success
end
test "should get edit" do
get :edit
assert_response :success
end
test "should get show" do
get :show
assert_response :success
end
end
This is my routes.rb
Rails.application.routes.draw do
devise_for :users
authenticated :user do
root 'du#dashboard', as: "authenticated_root"
end
resources :goals
root 'du#Home'
end
My goals_controller.rb
class GoalsController < ApplicationController
before_filter :authenticate_user!, only: [:new]
def new
end
def edit
end
def show
end
private
def find_user
#user = User.find(params[:user_id])
end
def find_goal
#goal = Goal.find(params[:id])
end
end
I find it weird that if I use get 'goals/edit' instead of resources :goals the test passes.
Thank you very much for any guideline.
When you use resources :goals Rails generates for you the following routes (RESTful):
goals GET /goals(.:format) goals#index
POST /goals(.:format) goals#create
new_goal GET /goals/new(.:format) goals#new
edit_goal GET /goals/:id/edit(.:format) goals#edit
goal GET /goals/:id(.:format) goals#show
PATCH /goals/:id(.:format) goals#update
PUT /goals/:id(.:format) goals#update
DELETE /goals/:id(.:format) goals#destroy
As you can see, to hit the edit action /goals/:id/edit you need to pass an :id. That way, in your controller you'll be able to find the record by the given :id => Goal.find(params[:id]). So, in your tests you need to pass this :id, something like:
get :edit, id: 1 # mapping to /goals/1/edit
If you manually add this route get 'goals/edit', it works because it maps directly to /goals/edit (NOTE there is no :id).
Btw, I recommend you to review the official Routing guides: http://guides.rubyonrails.org/routing.html
#goal = Goal.create(your params here) or use factory girl gem or fixtures
you should pass id get :edit ,id: #goal
useful article
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 have my brands controller in app/controllers/merchant/brands_controller.rb
I'm trying to write a functional test for it. I've defined test class as
require 'test_helper'
class Merchant::BrandsControllerTest < ActionController::TestCase
include Devise::TestHelpers
setup do
#user = users(:one)
sign_in #user
#brand= brands(:one)
end
test "should get index" do
get :index
assert_response :success
end
end
but the tests throw an error saying
ActionController::RoutingError: No route matches {:controller=>"merchant/brands", :action=>"new"}
Why is it using 'merchant/brands' as controller name?
Or can I specify custom route to make a request to 'new' method?
My routes look like this
namespace :merchant do
resources :accounts do
resources :brands
end
end
I
It seems you forgot the accounts part of your route.
Try with
class Merchant::Accounts::BrandsControllerTest
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'