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
Related
I've got controller below controller:
module Api
module V1
module Account
class PasswordsController < Devise::PasswordsController
respond_to :json
def create
# some code
end
def update
# some code
end
def is_token_valid
::Account.find_by(reset_password_token: params[:token])
end
end
end
end
end
I want to setup an endpoint for front-end dev where he will check if reset_password_token exist in DB (devise here). I don't know how to made a path like: /api/v1/account/password/is_token_valid
My routes:
namespace :api, defaults: { format: :json } do
namespace :v1 do
namespace :account do
devise_for :accounts, singular: 'account', path: '', controllers: {
sessions: 'api/v1/account/sessions',
registrations: 'api/v1/account/registrations',
confirmations: 'api/v1/account/confirmations',
passwords: 'api/v1/account/passwords',
}
end
resource :account, only: [:show]
EDIT
routes:
root#b2faabb49f91:/usr/src/app# rake routes | grep account
new_account_session GET /api/v1/account/sign_in(.:format) api/v1/account/sessions#new {:format=>:json}
account_session POST /api/v1/account/sign_in(.:format) api/v1/account/sessions#create {:format=>:json}
destroy_account_session DELETE /api/v1/account/sign_out(.:format) api/v1/account/sessions#destroy {:format=>:json}
new_account_password GET /api/v1/account/password/new(.:format) api/v1/account/passwords#new {:format=>:json}
edit_account_password GET /api/v1/account/password/edit(.:format) api/v1/account/passwords#edit {:format=>:json}
account_password PATCH /api/v1/account/password(.:format) api/v1/account/passwords#update {:format=>:json}
It used to work but after some changes, Action Controller is catching an exception
Routing Error: No route matches [GET] "/clock_events/1/clock_in"
routes.rb file:
Rails.application.routes.draw do
root to: 'clock_events#index'
get '/register', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
get '/logout', to: 'sessions#destroy'
resources :clock_events, except: [:destroy] do
member do
post 'clock_in', to: 'clocks#clock_in'
post 'clock_out', to: 'clocks#clock_out'
end
end
resources :users, except: [:destroy]
end
You've defined clock_in with the post http verb, here:
resources :clock_events, except: [:destroy] do
member do
post 'clock_in', to: 'clocks#clock_in'
post 'clock_out', to: 'clocks#clock_out'
end
end
But, you're trying to use the get verb, as indicated here:
Routing Error: No route matches [GET] "/clock_events/1/clock_in"
You need to either change your path to use the get verb:
resources :clock_events, except: [:destroy] do
member do
get 'clock_in', to: 'clocks#clock_in'
post 'clock_out', to: 'clocks#clock_out'
end
end
Or modify your link (or whatever) to use the post method.
Also, your clock_in and clock_out actions are called on the clocks controller, not the clock_events controller, as indicated by your to: directive:
resources :clock_events, except: [:destroy] do
member do
post 'clock_in', to: 'clocks#clock_in'
post 'clock_out', to: 'clocks#clock_out'
end
end
Are you sure you don't want to use the ClockEventsController? If so, you could do:
resources :clock_events, except: [:destroy] do
member do
post :clock_in
post :clock_out
end
end
In which case you would get:
clock_in_clock_event POST /clock_events/:id/clock_in(.:format) clock_events#clock_in
clock_out_clock_event POST /clock_events/:id/clock_out(.:format) clock_events#clock_out
clock_events GET /clock_events(.:format) clock_events#index
POST /clock_events(.:format) clock_events#create
new_clock_event GET /clock_events/new(.:format) clock_events#new
edit_clock_event GET /clock_events/:id/edit(.:format) clock_events#edit
clock_event GET /clock_events/:id(.:format) clock_events#show
PATCH /clock_events/:id(.:format) clock_events#update
PUT /clock_events/:id(.:format) clock_events#update
I have a rails api application where I am using Devise gem for user management. I created a user model off the devise gem. After that, I noticed that I have two same routes listed in the rake routescommand. I want POST (/users) to call api/v1/users#create action first and then call devise/registrations#create.
user_registration POST /users(.:format) devise/registrations#create
api_users POST /users(.:format) api/v1/users#create {:format=>:json}
When I test POST (/users) using users_controller_spec file, api/v1/users#create action is called. However, when I do a POST (/users) using POSTMAN, the logs indicates that devise/registrations#createaction is called instead.
How do I correct this so that the POST (/users) I do using POSTMAN or curl calls api/v1/users#create first to create the user model and then calls devise/registrations#create to register the user?
I am not 100% sure how devise works so any help here would be helpful.
This is my config/routes.rb
Rails.application.routes.draw do
devise_for :users
# Api definition
namespace :api, defaults: { format: :json }, path: '/' do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
# We are going to list our resources here
resources :users, only: [:show, :create, :update, :destroy]
resources :sessions, only: [:create, :destroy]
end
end
end
So, the thing with Rails Routes is, when you make a request, routes are checked as they are defined in the routes.rb from top to bottom.
Now, when you make a request via POSTMAN, the /users path matches with a path generated via devise_for, as it is the first line in the file.
Now, when you are writing tests for the controller, you are not really accessing /users, you are just telling the api/v1/users_controller to invoke the create method, which is bound to hit the api/v1/users#create
Now, a way you can resolve this conflict is by changing what devise names its routes. If you do something like this:
Rails.application.routes.draw do
devise_for :users, path: 'customer'
# Api definition
namespace :api, defaults: { format: :json }, path: '/' do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
# We are going to list our resources here
resources :users, only: [:show, :create, :update, :destroy]
resources :sessions, only: [:create, :destroy]
end
end
end
This is what the devise routes will be:
new_user_session GET /customer/sign_in(.:format) devise/sessions#new
user_session POST /customer/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /customer/sign_out(.:format) devise/sessions#destroy
user_password POST /customer/password(.:format) devise/passwords#create
new_user_password GET /customer/password/new(.:format) devise/passwords#new
edit_user_password GET /customer/password/edit(.:format) devise/passwords#edit
...
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
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