I'm having some difficulty getting all the RESTful routes to be setup correctly. I've taken the simplest of simple steps in my app so far.
Create new rails app
Create new controller with RESTful actions
Add resources to routes.rb
And yet 4 out of my 7 actions fail the default tests. Can anyone please explain why?
rails generate controller Employees new create update edit destroy index show
And here's the corresponding controller, employees_controller.rb
class EmployeesController < ApplicationController
def new
end
def create
end
def update
end
def edit
end
def destroy
end
def index
end
def show
end
end
Now I add the resources to routes.rb
Rails.application.routes.draw do
resources :employees
end
All the routes seem to be there, based on the output of rake routes
Prefix Verb URI Pattern Controller#Action
employees GET /employees(.:format) employees#index
POST /employees(.:format) employees#create
new_employee GET /employees/new(.:format) employees#new
edit_employee GET /employees/:id/edit(.:format) employees#edit
employee GET /employees/:id(.:format) employees#show
PATCH /employees/:id(.:format) employees#update
PUT /employees/:id(.:format) employees#update
DELETE /employees/:id(.:format) employees#destroy
But now when I run the default tests, I get 4 errors:
# Running:
.EEEE..
Finished in 0.267712s, 26.1475 runs/s, 11.2061 assertions/s.
1) Error:
EmployeesControllerTest#test_should_get_update:
ActionController::UrlGenerationError: No route matches {:action=>"update", :controller=>"employees"}
test/controllers/employees_controller_test.rb:15:in `block in <class:EmployeesControllerTest>'
2) Error:
EmployeesControllerTest#test_should_get_destroy:
ActionController::UrlGenerationError: No route matches {:action=>"destroy", :controller=>"employees"}
test/controllers/employees_controller_test.rb:25:in `block in <class:EmployeesControllerTest>'
3) Error:
EmployeesControllerTest#test_should_get_show:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"employees"}
test/controllers/employees_controller_test.rb:35:in `block in <class:EmployeesControllerTest>'
4) Error:
EmployeesControllerTest#test_should_get_edit:
ActionController::UrlGenerationError: No route matches {:action=>"edit", :controller=>"employees"}
test/controllers/employees_controller_test.rb:20:in `block in <class:EmployeesControllerTest>'
7 runs, 3 assertions, 0 failures, 4 errors, 0 skips
Lastly, here is the contents of employees_controller_test.rb. As I said, these are the default tests auto-created by Rails upon generation of the controller.
require 'test_helper'
class EmployeesControllerTest < ActionController::TestCase
test "should get new" do
get :new
assert_response :success
end
test "should get create" do
get :create
assert_response :success
end
test "should get update" do
get :update
assert_response :success
end
test "should get edit" do
get :edit
assert_response :success
end
test "should get destroy" do
get :destroy
assert_response :success
end
test "should get index" do
get :index
assert_response :success
end
test "should get show" do
get :show
assert_response :success
end
end
according to dimakura's answer you have to change some routes in your test
the update method is a put (or a patch for partial changes in rails4)
test "should get update" do
put :update
assert_response :success
end
and for your edit, delete and show routes, the id is missing
test "should get edit" do
get :edit, id: 2
assert_response :success
end
Your controller test probably looks like:
class EmployeesControllerTest < ActionController::TestCase
test "should get create" do
get :create
assert_response :success
end
# other tests not shown
end
You should change it to this:
class EmployeesControllerTest < ActionController::TestCase
test "should get create" do
post :create
assert_response :success
end
# other tests should be changed accordingly
end
Use patch or put method for update, and delete for delete actions.
Related
I've been following the Michael Hartl tutorial for learning rails and have been doing pretty well thus far, but I'm stumped on this issue which I've encountered repeatedly. I'm not skilled enough to know if there is a configuration problem in my environment or something else, but this makes NO sense to me.
In ANY of the controller tests I attempt to run, I can never get my helper URL methods to work. As an example:
test "should redirect home when not an admin" do
log_in_as(#other_user)
assert_no_difference 'User.count' do
delete user_path(#user)
end
assert redirect_to root_url
end
Generates the following error:
ERROR["test_should_redirect_home_when_not_an_admin", UsersControllerTest, 0.9899668790167198]
test_should_redirect_home_when_not_an_admin#UsersControllerTest (0.99s)
ActionController::UrlGenerationError: ActionController::UrlGenerationError: No route matches {:action=>"/users/762146111", :controller=>"users"}
test/controllers/users_controller_test.rb:60:in `block (2 levels) in <class:UsersControllerTest>'
test/controllers/users_controller_test.rb:59:in `block in <class:UsersControllerTest>'
Even simple tests like
test "should redirect index when not logged in" do
get users_path
assert_redirected_to login_url
end
Produce the same error:
ERROR["test_should_redirect_index_when_not_logged_in", UsersControllerTest, 1.5291320629185066]
test_should_redirect_index_when_not_logged_in#UsersControllerTest (1.53s)
ActionController::UrlGenerationError: ActionController::UrlGenerationError: No route matches {:action=>"/users", :controller=>"users"}
test/controllers/users_controller_test.rb:34:in `block in <class:UsersControllerTest>'
Everything I've googled about this issue hasn't helped, because for some reason I cannot determine the user_path method (or any other similar method) somehow thinks the action I'm trying to take in my controller is the path!
I've verified that my routes file is configured correctly.
Rails.application.routes.draw do
root 'static_pages#home'
get '/help' => 'static_pages#help'
get '/about' => 'static_pages#about'
get '/contact' => 'static_pages#contact'
get '/signup' => 'users#new'
post '/signup' => 'users#create'
get '/login' => 'sessions#new'
post '/login' => 'sessions#create'
delete '/logout' => 'sessions#destroy'
get 'sessions/new'
resources :users
end
I've checked that running "rails routes" has the correct routes. I've even checked in rails console that "app.user_path(1)" spits out a valid path.
At this point I'm just beyond stumped as to why these helper methods don't seem to be helping... I also don't know what they're actually called so my googling has been fairly fruitless.
To get around this issue in the tutorial, I've been using syntax like
patch :edit, { id: #user }, params: { user: { name: #user.name,
email: #user.email }}
Or
test "should redirect index when not logged in" do
get :index
assert_redirected_to login_url
end
Which seems to work.
Also here is one of my test files if that's helpful:
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:michael)
#other_user = users(:archer)
end
test "should get new" do
get :new
assert_response :success
end
test "should redirect edit when user not logged in" do
get :edit, params: { id: #user }
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect update when user not logged in" do
patch :edit, { id: #user }, params: { user: { name: #user.name,
email: #user.email }}
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect index when not logged in" do
# get users_path
get :index
assert_redirected_to login_url
end
test "should redirect destroy when not logged in" do
assert_no_difference 'User.count' do
delete user_path(#user)
end
assert redirect_to login_url
end
test "should redirect home when not an admin" do
log_in_as(#other_user)
assert_no_difference 'User.count' do
delete user_path(#user)
end
assert redirect_to root_url
end
end
Please let me know what other files I can post to be helpful.
I had the same issue and I fixed it by changing the file 'users_controller_test.rb' file replacing:
class UsersControllerTest < ActionController::TestCase
for
class UsersControllerTest < ActionDispatch::IntegrationTest
But first, in your case, check that you have in your Gemfile the line:
gem 'rails', '5.0.1'
as the tutorial shows.
I can also see that you have the following test:
test 'should get new' do
get :new
assert_response :success
end
When you make the correction you'll have to change the above test to:
test 'should get new' do
get new_user_path
assert_response :success
end
After that, run your tests and you should have them all passed.
Hope it helps
I'm trying to do some units test, this is my first time.
I don't really understand why there is No route matches.
When i run $ rake test test/controllers/products_controller_test.rb
i get this in the output of the console:
1) Error:
ProductsControllerTest#test_should_get_edit:
ActionController::UrlGenerationError: No route matches {:action=>"edit", :controller=>"products"}
test/controllers/products_controller_test.rb:20:in `block in <class:ProductsControllerTest>'
2) Error:
ProductsControllerTest#test_should_get_show:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"products"}
test/controllers/products_controller_test.rb:35:in `block in <class:ProductsControllerTest>'
3) Error:
ProductsControllerTest#test_should_get_create:
ActionController::ParameterMissing: param is missing or the value is empty: product
app/controllers/products_controller.rb:59:in 'product_params'
app/controllers/products_controller.rb:18:in 'create'
test/controllers/products_controller_test.rb:15:in `block in <class:ProductsControllerTest>'
4) Error:
ProductsControllerTest#test_should_get_update:
ActionController::UrlGenerationError: No route matches {:action=>"update", :controller=>"products"}
test/controllers/products_controller_test.rb:25:in `block in <class:ProductsControllerTest>'
5) Error:
ProductsControllerTest#test_should_get_destroy:
ActionController::UrlGenerationError: No route matches {:action=>"destroy", :controller=>"products"}
test/controllers/products_controller_test.rb:30:in `block in <class:ProductsControllerTest>'
7 runs, 2 assertions, 0 failures, 5 errors, 0 skips
This is the products_controller_test.rb file:
require 'test_helper'
class ProductsControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
end
test "should get new" do
get :new
assert_response :success
end
test "should get create" do
get :create
assert_response :success
end
test "should get edit" do
get :edit
assert_response :success
end
test "should get update" do
get :update
assert_response :success
end
test "should get destroy" do
get :destroy
assert_response :success
end
test "should get show" do
get :show
assert_response :success
end
end
routes.rb file:
Rails.application.routes.draw do
resources :products
end
For all these routes (edit, update, destroy), you need to say which product you're editing/updating/destroying. If Rails doesn't know it, it can't draw the route for you.
For edit, for example, the full route would be products/:product_id/edit. So Rails will need to 'fill in' the :product_id key. If you leave it blank the route breaks.
In your code, then, if you're calling get :edit, you need to specify a product id. Like so:
get :edit, product_id: products(:test_product).id
(using the fixtures explained in the Rails test tutorial here)
Following a rails tutorial but when off on a slight tangent and now cant get a test to pass.
Below is my routes file and my test file. The home test is failing and this line , to: "static_pages#home", as: "home" is the line that makes it appear. i.e remove this and it'll pass. I was wondering why someone could explain why this is failing and how to alter the test to make it pass but keeping this line in?
My routes file:
Rails.application.routes.draw do
resources :static_pages
get 'static_pages/help'
get 'static_pages/test'
get 'static_pages/home', to: "static_pages#home", as: "home"
root 'application#hello'
end
My test file:
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
test "should get home" do
get static_pages_home_url
assert_response :success
end
test "should get help" do
get static_pages_help_url
assert_response :success
end
test "should get test" do
get static_pages_test_url
assert_response :success
end
end
static_pages_home_url is the default helper method for that route with controller static_pages and action home but you set the name as home so your test should be
test "should get home" do
get home_url
assert_response :success
end
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) }