How to replace 'show' with 'download' in rails routes? - ruby-on-rails

This is driving me crazy. Rails is saying I don't have a controller action defined, but I clearly do in rake routes.
What am I missing here?
spec/controllers/api/v1/files_controller_spec.rb:
describe "download action" do
after do
get :download, id: file.id
end
it "returns http status 200 OK" do
expect(response).to have_http_status(200)
end
end
Failure message of no route matches action download:
Failures:
1) Api::V1::FilesController download action returns http status 200 OK
Failure/Error: get :download, id: file.id
ActionController::UrlGenerationError:
No route matches {:action=>"download", :controller=>"api/v1/files", :id=>"2"}
config/routes.rb:
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :files, only: [:index, :create]
get "files/:id", to: "file#download", as: "file"
end
end
rake routes | grep file:
api_v1_files GET /api/v1/files(.:format) api/v1/files#index {:format=>:json}
POST /api/v1/files(.:format) api/v1/files#create {:format=>:json}
api_v1_file GET /api/v1/files/:id(.:format) api/v1/file#download {:format=>:json}

You can add more routes to a resource with a block like so:
resources :files, only: [:index, :create] do
member do
get 'download'
end
end

Related

ActionController::UrlGenerationError: No route matches {:action=>"index", :controller=>"api/v1/topics", :format=>:json}

I have my topics_controller inside the folder (api/v1/) as
class Api::V1::TopicsController < ApplicationController
def index
#topics = Topic.all
render json: #topics
end
end
When I try to write rspec for above code as :
require 'rails_helper'
require 'spec_helper'
RSpec.describe Api::V1::TopicsController do
describe "GET #index" do
it "should return a successful response" do
get :index, format: :json
expect(response).to be_success
end
end
end
I'm getting error:
ActionController::UrlGenerationError: No route matches {:action=>"index", :controller=>"api/v1/topics", :format=>:json}.
But I have correct route I don't know why it is showing like that. Any solution are most welcomed.
I have my route as:
Rails.application.routes.draw do
namespace :api, defaluts: {format: :json} do
namespace :v1 do
resources :topics
end
end
end
Typo in routes:
namespace :api, defaluts: {format: :json} => defaults
You have a typo. defaluts: {format: :json} should be defaults: {format: :json}
Okay guys i had a typo in 'defaults'. Everyone will make typo mistakes so you need not downvote my question.

Case insensitive routes in Rails

How can I have a portion of a route Capitalized? For example I have a route scim/v2/user but I'd like it to be scim/v2/User (User capitalized). How can I achieve this while still using resource.
Routes file:
namespace :scim, defaults: { format: :json } do
namespace :v2 do
resource :user, only: [:create, :update, :show]
end
end
When I run $rake routes, I get this:
scim_v2_user POST /scim/v2/user(.:format) scim/v2/users#create {:format=>:json}
GET /scim/v2/user(.:format) scim/v2/users#show {:format=>:json}
PATCH /scim/v2/user(.:format) scim/v2/users#update {:format=>:json}
PUT /scim/v2/user(.:format) scim/v2/users#update {:format=>:json}
I'd like to either have the routes be /scim/v2/User or have them remain the same but have a way of mapping /scim/v2/User to /scim/v2/user.
By default resource wants a direct mapping between the resource name and the controller, but you can simplify use an upper case resource name and manually specify the controller to get around this:
namespace :scim, defaults: { format: :json } do
namespace :v2 do
resource :User, :controller => 'users', only: [:create, :update, :show]
end
end
Generates
Prefix Verb URI Pattern Controller#Action
scim_v2_User GET /scim/v2/User(.:format) scim/v2/users#show {:format=>:json}
PATCH /scim/v2/User(.:format) scim/v2/users#update {:format=>:json}
PUT /scim/v2/User(.:format) scim/v2/users#update {:format=>:json}
POST /scim/v2/User(.:format) scim/v2/users#create {:format=>:json}
I was able to solve this by manually specifying the path and controller. I specified that path should be Users (capitalized). Below is code in my routes file:
namespace :scim, defaults: { format: :json } do
namespace :v2 do
resources :user,
path: "Users",
controller: "users",
only: [:create, :update, :index, :show]
end
end

` No route matches` error for Nested Resources Controller Spec - Rails, Rspec

I keep getting No route matches error for a nested resource #create action. Here is what I got:
routes:
...
resources :users, only: [:show, :create] do
resources :filters, only: [:new,:create]
end
...
controller spec:
...
context 'with valid attributes' do
it "creates new Filter" do
expect{
post :create, {:filter => attributes_for(:filter)}
}.to change(Filter, :count).by(1)
end
...
error:
No route matches {:action=>"create", :controller=>"filters", :filter=>{[long filter hash]}
Because it is nested, you also need to include the ID for the parent object that the filter will belong to.
post :create, user_id: <some_user_id>, {:filter => attributes_for(:filter)}

Rails 3: respond_with errors on undefined URL helper

I have an Artwork model that is manipulated only by API endpoints right now. (You'll see why this is important shortly). Those API endpoints are declared like so in my routes.rb file:
namespace :api do
namespace :v1, :defaults => { :format => :json } do
resources :artworks, :only => [:create, :destroy, :index, :show, :update]
This results in the following routes:
api_v1_artworks GET /api/v1/artworks(.:format) api/v1/artworks#index {:format=>:json}
POST /api/v1/artworks(.:format) api/v1/artworks#create {:format=>:json}
api_v1_artwork GET /api/v1/artworks/:id(.:format) api/v1/artworks#show {:format=>:json}
PUT /api/v1/artworks/:id(.:format) api/v1/artworks#update {:format=>:json}
DELETE /api/v1/artworks/:id(.:format) api/v1/artworks#destroy {:format=>:json}
Relevant code:
class Api::V1::ArtworksController < Api::V1::ApiController
def create
artwork = Artwork.create(artwork_params)
respond_with artwork
end
The Problem
When #create succeeds, respond_with chokes:
`undefined method `artwork_url' for #<Api::V1::ArtworksController:0x007fea1b4c67f8>`
It's expecting the helper for the HTTP Location to be artwork_url. How do I tell it to use api_v1_artwork_url instead? Can I alias the URL helper?
In this case, you'd need to specify the namespace for the responder. Try:
respond_with :api, :v1, artwork

RSpec RoutingError for nested controller

I'm testing a nested controller and get the following error:
1) Checklists::ItemsController index action should render index template
Failure/Error: get :index, :checklist_id => checklist.id
ActionController::RoutingError:
No route matches {:checklist_id=>1, :controller=>"checklists/items"}
In the browser loading /checklists/1/items loads fine.
Am I missing something in the spec?
The routes:
resources :checklists do
resources :items, :controller => "Checklists::Items"
end
The controller located in namespaced folder (/app/controllers/checklists/items_controller.rb):
class Checklists::ItemsController < ApplicationController
respond_to :html, :json
def index
#checklist_items = #checklist.items
respond_with #checklist_items
end
end
The spec (/spec/controllers/checklists/items_controller_spec.rb):
describe Checklists::ItemsController do
let(:user) { Factory :user, :role => 'admin' }
let(:checklist) { Factory(:checklist) }
let(:checklist_item) { Factory(:checklist_item) }
before(:each) do
sign_in_to(controller, user)
Checklist.stub(:find => checklist)
end
it "index action should render index template" do
get :index, :checklist_id => checklist.id
response.should render_template(:index)
end
end
Update: Routes for checklist items
checklist_items GET /checklists/:checklist_id/items(.:format) {:action=>"index", :controller=>"Checklists::Items"}
POST /checklists/:checklist_id/items(.:format) {:action=>"create", :controller=>"Checklists::Items"}
new_checklist_item GET /checklists/:checklist_id/items/new(.:format) {:action=>"new", :controller=>"Checklists::Items"}
edit_checklist_item GET /checklists/:checklist_id/items/:id/edit(.:format) {:action=>"edit", :controller=>"Checklists::Items"}
checklist_item GET /checklists/:checklist_id/items/:id(.:format) {:action=>"show", :controller=>"Checklists::Items"}
PUT /checklists/:checklist_id/items/:id(.:format) {:action=>"update", :controller=>"Checklists::Items"}
DELETE /checklists/:checklist_id/items/:id(.:format) {:action=>"destroy", :controller=>"Checklists::Items"}
It turns out the solution to the problem was in the routes:
I changed
resources :items, :controller => "Checklists::Items"
to
resources :items, :controller => "checklists/items"
and it works now

Resources