Rails 4 routing excluding :new action breaks rspec routing tests - ruby-on-rails

I have a simple controller that is supposed to respond to just show and index actions. In order to tighten up my routes, I have added the condition to only handle :show and :index. The problem is that this appears to force the show action to respond to pro_infos/new, where it presumably sees 'new' as the :id param.
Not a real problem in itself, but it breaks my rspec routing test for new to not be routable.
From routes:
resources :masters, only: [:show, :index, :new, :create] do
resources :pro_infos, only: [:show, :index]
end
From rspec routing
it "routes to #new" do
expect(:get => "masters/2/pro_infos/new").not_to be_routable
end
rake routes |grep pro_infos returns:
master_pro_infos GET /masters/:master_id/pro_infos(.:format) pro_infos#index
master_pro_info GET /masters/:master_id/pro_infos/:id(.:format) pro_infos#show
I understand that I can just cut out the routing test for the new action, but for the sake of consistency across my application I would prefer to test for the routing not responding to it. What is the correct / best-practice approach to this?

You could add a constraint (seen here) to your route to only allow integer IDs like this:
resources :masters, only: [:show, :index, :new, :create] do
resources :pro_infos, only: [:show, :index], constraints: { id: /\d+/ }
end

Related

Rails routes: GET method redirecting to show method

I have simple controller and routes file.
In my route and controller i have created a module. I wrote a simple method which is redirecting me show. I am not sure why.
Controller
module Seller
class CampaignsController < Seller::BaseController
before_action :confirm_logged_in
def viewAllCampaigns
#campaigns = Campaign.all
end
def show
end
end
end
Routes file
scope module: 'seller' do
#namespace :power do
resources :dashboard, only: [:index]
resources :sessions, only: [:create, :destroy]
resources :campaigns, only: [:index, :create, :show, :update, :destroy]
get 'viewAllCampaigns' => 'campaigns#viewAllCampaigns'
end
Output
Started GET "/campaigns/viewAllCampaigns" for 127.0.0.1 at 2015-10-12 17:39:43 +0500
Processing by Seller::CampaignsController#show as HTML
Parameters: {"id"=>"viewAllCampaigns"}
Rendered seller/campaigns/show.html.erb (0.1ms)
I am hitting http://localhost:3000/campaigns/viewAllCampaigns in browser.
Ideally your routes should be defined like this.
resources :campaigns, only: [:index, :create, :show, :update, :destroy] do
get 'viewAllCampaigns', on: :collection
end
The first comment on the routes.rb file is The priority is based upon order of creation: first created -> highest priority. This is the reason your route is redirecting to show. Rails is treating this url as campain/:id.
Routes are tested in order, from top to bottom. The show route you've added for the campaigns resource will look for urls matching this pattern:
/campaigns/:id
/campaigns/viewAllCampaigns matches this, so it will do the show action., with params[:id] = "viewAllCampaigns"
Move the special case route up above the resources#campaigns route to fix this, then it will catch the url first.
get 'viewAllCampaigns' => 'campaigns#viewAllCampaigns'
resources :campaigns, only: [:index, :create, :show, :update, :destroy]
It takes the following get request as a show action because show expects campaigns/:id, and it assumes 'viewAllCampaigns' is an id in this instance:
/campaigns/viewAllCampaigns
Your link_to should just be pointing to the following:
'/viewAllCampaigns'
Your route structure isn't really RESTful, but that's a separate topic.

rspec ActionController::UrlGenerationError for create action in namespaced admin that is nested

I'm getting this error in my controller spec for my create action
No route matches {:action=>"create", :assessment=>{:course_id=>"1", :curriculum_id=>"1"}, :controller=>"admin/assessments"}
Here is my controller spec:
it "sets the flash success" do
set_current_admin
course = Fabricate(:course)
post :create, assessment: { course_id: course.id, curriculum_id: course.curriculum.id }
expect(flash[:success]).not_to be_blank
end
The error occurs on the post :create.. line.
Here is my create action for assessments:
def create
#assessment = Assessment.new(assessment_params.merge!(course_id: Course.find(params[:course_id]).id))
if #assessment.save
flash[:success] = "You have created your assessment."
redirect_to curriculum_course_assessment_path(#assessment.course.curriculum, #assessment.course, #assessment)
else
...
end
end
And, here is my routing for the assessments:
resources :curriculums, only: [:index, :show] do
resources :courses, only: [:show] do
resources :assessments, only: [:show]
namespace :admin do
resources :assessments, only: [:index, :new, :create, :edit, :update]
end
end
end
Here is the line from my rake routes...
POST /curriculums/:curriculum_id/courses/:course_id/admin/assessments(.:format) admin/assessments#create
When I actually run the create action in the browser, it works fine, so I'm guessing that it's a problem with my spec's syntax. Any advice on this would be much appreciated. (I realize that I'm double-nesting by resources here which is not generally the best practice, but I couldn't find any other way to access the curriculums & courses params.)
You're nesting the course_id and curriculum_id parameters inside an assessment hash - in the route, they are not nested.

use :only helper in routes

I have a project where user can download files. Now, i want another page for show all users. so, i add a method all_users in my addfiles_controller. I have also a view page all_users.html.erb for that. But The ploblem is with the routes.rb file . Here I want to ensure user can only use :index, :new, :create, :destroy, :all_users paths.
How can i set this :only helper in my routes.rb file, like
resources :addfiles, only: [:index, :new, :create, :destroy, :all_users]
My routes.rb file::
resources :addfiles do
collection do
get 'all_users'
end
end
you shouldn't write all_users to only, because only/except related just to standard actions index, show, new, edit, create, update, destroy which resources define by default
resources :addfiles, only: [:index, :new, :create, :destroy] do
collection do
get 'all_users'
end
end

How to create routes path into resource in rails 3

I understand resource and path routes in rails 3 but I do not know is there any way to have both routes ? I try this routes but it not work for me, this is the routes:
resources :roles, only: [:index, :create, :show, :update]
get '/roles/:id' => 'roles#available_users'
How can we routes to use both routes ?
thankyou very much
Routes
What you're asking for cannot be done, as you'll be using the same "route" for different controller actions:
#config/routes.rb
resources :roles, only: [:index, :create, :show, :update] #-> domain.com/roles/:id - roles#show
If you then create another route for domain.com/roles/:id, Rails will just take the first which it finds in the routes file
--
The way to fix your issue is likely to be down to the following:
#config/routes.rb
resources :roles, except: [:edit, :destroy] do
get :available_users # -> domain.com/roles/:id/available_users
end
This will take you to the roles#available_users action, providing you with the ability to load the view you wish (to display the users for a particular role)
For a more defined explanation, I'd recommend checking out the nested_resources part of the Rails routing system
If I understand you correctly you want something like this:
resources :roles, only: [:index, :create, :update] do
get '/roles/:id' => 'roles#available_users'
end
Correct?
Just add an "do" behind the closing ] and an end after the custom routes.
Edit: Apparently I got wrong. ;) What you could do is:
resources :roles, only: [:index, :create, :show, :update] do
get '/roles/:id/available' => 'roles#available_users'
end

Routing Error : uninitialized constant when split controller routes into namespaced route

I have routes like this below. Is it possible if I have routes like this ?
#config/routes
resources :subscribers, only: [:index, :show]
namespace :admin do
resources :subscribers, only: [:new, :edit, :update, :create, :destroy]
end
I have tried to run rake routes and the result is
admin_subscribers POST /admin/subscribers(.:format) admin/subscribers#create
new_admin_subscriber GET /admin/subscribers/new(.:format) admin/subscribers#new
edit_admin_subscriber GET /admin/subscribers/:id/edit(.:format) admin/subscribers#edit
admin_subscriber PUT /admin/subscribers/:id(.:format) admin/subscribers#update
DELETE /admin/subscribers/:id(.:format) admin/subscribers#destroy
subscribers GET /subscribers(.:format) subscribers#index
subscriber GET /subscribers/:id(.:format) subscribers#show
the result was appropriate with my expectation, but when i run my RSpec i got errors
Routing Error
uninitialized constant Admin::SubscribersController
Try running rake routes for more information on available routes.
I added this code below in my Rspec Helper too
#spec/spec_helper.rb
Spork.each_run do
###
if /spork/i =~ $0 || RSpec.configuration.drb?
ActiveSupport::Dependencies.clear
end
###
end
But, if I fire my browser to htt**://l*alhost:3000/admin/subscribers/new, everything is fine.
Am I missing something ?
As stated in the docs
If you want to route /admin/subscribers to SubscribersController (without the Admin:: module prefix), you could use scope instead of namespace
#config/routes
resources :subscribers, only: [:index, :show]
scope "/admin" do
resources :subscribers, only: [:new, :edit, :update, :create, :destroy]
end
I don't think there's much need for you to namespace this under admin. You could just fill in all the actions on SubscribersController and set the permissions on create, update etc. appropriately.

Resources