I am learning rails api, and below is my rails routes file
Rails.application.routes.draw do
namespace :api, defaults: { format: :json }, path: '/', constraints: { subdomain: 'api' } do
resources :posts, only: [:index, :show]
end
end
when i tried to run the server with
http://localhost:3000/posts/1
it gives me the error no routes matches, but It works with the below
http://api.lvh.me:3000/posts/1
what is the difference between two and how does it works.It is a way to run the server with default localhost:3000 when using the api
rake routes
Prefix Verb URI Pattern Controller#Action
api_posts GET /posts(.:format) api/posts#index {:format=>:json, :subdomain=>"api"}
api_post GET /posts/:id(.:format) api/posts#show {:format=>:json, :subdomain=>"api"}
constraints: { subdomain: 'api' }
This is stating that this route is only present for requests that originate from the specified subdomain.
http://guides.rubyonrails.org/routing.html#request-based-constraints
To expand on my answer, I will ask you if the API is a component of a larger Rails application? If not, the constraint is unneeded as you can take of this via DNS settings through you domain hosting service.
Related
In building a Rails API, I declared my routes file as:
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
root 'budgets#index'
resources :users do
resources :budgets
end
post '/login', to: 'sessions#create'
post '/logout', to: 'sessions#destroy'
resources :budgets do
resources :budget_totals
end
end
end
end
However, after running the rails routes command, I found that the "new" and "edit" routes are missing. How do I rectify this?
The relevant portion of the rails routes response is:
Prefix Verb URI Pattern Controller#Action
api_v1_root GET /api/v1(.:format) api/v1/budgets#index
api_v1_user_budgets GET /api/v1/users/:user_id/budgets(.:format) api/v1/budgets#index
POST /api/v1/users/:user_id/budgets(.:format) api/v1/budgets#create
api_v1_user_budget GET /api/v1/users/:user_id/budgets/:id(.:format) api/v1/budgets#show
PATCH /api/v1/users/:user_id/budgets/:id(.:format) api/v1/budgets#update
PUT /api/v1/users/:user_id/budgets/:id(.:format) api/v1/budgets#update
DELETE /api/v1/users/:user_id/budgets/:id(.:format) api/v1/budgets#destroy
api_v1_users GET /api/v1/users(.:format) api/v1/users#index
POST /api/v1/users(.:format) api/v1/users#create
api_v1_user GET /api/v1/users/:id(.:format) api/v1/users#show
PATCH /api/v1/users/:id(.:format) api/v1/users#update
PUT /api/v1/users/:id(.:format) api/v1/users#update
DELETE /api/v1/users/:id(.:format) api/v1/users#destroy
api_v1_login POST /api/v1/login(.:format) api/v1/sessions#create
api_v1_logout POST /api/v1/logout(.:format) api/v1/sessions#destroy
api_v1_budget_budget_totals GET /api/v1/budgets/:budget_id/budget_totals(.:format) api/v1/budget_totals#index
POST /api/v1/budgets/:budget_id/budget_totals(.:format) api/v1/budget_totals#create
api_v1_budget_budget_total GET /api/v1/budgets/:budget_id/budget_totals/:id(.:format) api/v1/budget_totals#show
PATCH /api/v1/budgets/:budget_id/budget_totals/:id(.:format) api/v1/budget_totals#update
PUT /api/v1/budgets/:budget_id/budget_totals/:id(.:format) api/v1/budget_totals#update
DELETE /api/v1/budgets/:budget_id/budget_totals/:id(.:format) api/v1/budget_totals#destroy
api_v1_budgets GET /api/v1/budgets(.:format) api/v1/budgets#index
POST /api/v1/budgets(.:format) api/v1/budgets#create
api_v1_budget GET /api/v1/budgets/:id(.:format) api/v1/budgets#show
PATCH /api/v1/budgets/:id(.:format) api/v1/budgets#update
PUT /api/v1/budgets/:id(.:format) api/v1/budgets#update
DELETE /api/v1/budgets/:id(.:format) api/v1/budgets#destroy
Are you perhaps using the api_only app? Those do not generate New and Edit routes.
Did you create your app with the --api switch, such as: rails new my-api --api? The --api argument tells Rails that you want an API application only.
See "What Is Rails API?" and "Rails: Building a Ruby on Rails API-only app".
This is NOT a duplicate of this question, since I'm not using custom routes for this resource, nor slugs. I'm using Rails 5.
This is my router
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :node_categories, only: [:create, :update, :destroy]
resources :edge_categories, only: [:create, :update, :destroy]
resources :nodes, only: [:index, :create, :destroy] do
collection do
match '/bulk' => 'nodes#bulk', via: :post
end
end
Everything seems fine. rake routes prints the routes OK
api_v1_node_categories POST /api/v1/node_categories(.:format) api/v1/node_categories#create {:format=>:json}
api_v1_node_category PATCH /api/v1/node_categories/:id(.:format) api/v1/node_categories#update {:format=>:json}
PUT /api/v1/node_categories/:id(.:format) api/v1/node_categories#update {:format=>:json}
DELETE /api/v1/node_categories/:id(.:format)
The controllers are well namespaced and the tests are passing (not doing route tests in this project though). All other routes seem to work fine. Only this resource is giving troubles. Any request to any action returns 404 but the log shows no such requests, no errors nor exceptions, not nothing.
All client application, Postman and even curl behave the same way, a phantom 404 is returned, along with an empty response, with no record of it in the logs.
Any ideas?
Test
scope '/api' do
scope '/v1' do
...
end
end
Instead of namespace, I use that in my APIs.
The error turned out to be related to Fabio's (my router) route permissions. The new routes needed to be allowed.
It had nothing to do with Rails.
I did a rails 5 api with Sourcey tutorial and now i get a routing error.
Curl command curl -H "Authorization: Token token=8NjQH4YVWQdUIve4xDQBaArr" http://localhost:3000/v1/users display a 404 not found message and 'no route matches' is raised in my term where the server is running
No route matches [GET] "/v1/users"
So i checked rails routes. The output is:
v1_users GET /v1/users(.:format) api/v1/users#index {:subdomain=>"api"}
POST /v1/users(.:format) api/v1/users#create {:subdomain=>"api"}
v1_user GET /v1/users/:id(.:format) api/v1/users#show {:subdomain=>"api"}
PATCH /v1/users/:id(.:format) api/v1/users#update {:subdomain=>"api"}
PUT /v1/users/:id(.:format) api/v1/users#update {:subdomain=>"api"}
DELETE /v1/users/:id(.:format) api/v1/users#destroy {:subdomain=>"api"}
we notice we have GET /v1/users and /:id
How to solve this problem ?
routes.rb:
Rails.application.routes.draw do
constraints subdomain: 'api' do
scope module: 'api' do
namespace :v1 do
resources :users
end
end
end
end
Users_controller.rb and api_controller.rb are inside /app/controller/api/v1/.
If you need another part of the code (controllers, models ....) do not hesitate to ask
The problem is that your route has a subdomain constraint. So that your api would only be available at http://api.example.com/v1/users.
You cannot use subdomains with localhost without setting up a virtual host via apache or nginx, editing the hosts file or using a service like Ngrok.
You could also convert it to a path constraint instead:
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :users
end
end
end
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
...
I am using the Rails-Api (4) and I want only three routes for my namespaced routes file.
In my routes.rb file, I am trying to do this:
namespace :api do
namespace :v1 do
resources :documents, only: [:get, :create]
resource :system_status, only: [:get]
end
end
rake routes gets me only this:
Prefix Verb URI Pattern Controller#Action
api_v1_documents POST /api/v1/documents(.:format) api/v1/documents#create
If a take the the only: off, it works and gives me all the routes (which I don't want).
I also tried this:
namespace :api do
namespace :v1 do
post '/documents', to: 'documents#create'
get '/documents/:id', to: 'documents#show'
get '/system_status', to: 'system_status#show'
end
end
Gets me this odd output in rake routes:
Prefix Verb URI Pattern Controller#Action
api_v1_documents POST /api/v1/documents(.:format) api/v1/documents#create
api_v1 GET /api/v1/documents/:id(.:format) api/v1/documents#show
api_v1_system_status GET /api/v1/system_status(.:format) api/v1/system_status#show
Not sure what's up with documents#show getting me only api_v1 as it's prefix.
Looks like you're getting mixed up between HTTP verbs and their corresponding Rails actions. There is no resource route for :get, but there are two routes for a GET request, which are :index, and :show
Change your original resource-based routing to this instead:
namespace :api do
namespace :v1 do
resources :documents, only: [:show, :create]
resource :system_status, only: [:show]
end
end
And that should give you the proper routes, plus the correct URL helper prefixes.