Api rails: no route matches - ruby-on-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

Related

New and Edit Routes missing in Rails Resources routes

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".

How to get the sent parameters with POST (without form) on rails

I just only want to make a test and trying to understand the routes on rails. This is what I have on my controller:
class ItemsController < ApplicationController
def index
#data = params[:number]
end
end
and in index.html.erb
The number: <%= params[:number] %>
Well, if I made curl http://localhost:3000/?number=100 I can see on the view:
The number: 100
So, here everything is correct. But, I want to do the same, but with POST verb. So when I made curl -d "number=100" http://localhost:3000 I get the following error:
No route matches [POST] "/"
I have made:
def create
render plain: params[:number].inspect
end
to see the parameters, but as I said before, only works with GET verb.
So my question: How I can see the data sent by POST to the controller with curl and see the result on my view index.html.erb?
Note: On routes.rb I have:
Rails.application.routes.draw do
#get 'items/index'
resources :items
root 'items#index'
end
Notes: Based on the answer received, I have 2 more questions:
Why the verb GET works on http://localhost:3000/?number=100 and the same with http://localhost:3000/items/?number=100? Why the same does not happens with POST?
How can I remove the message No route matches [POST] "/" if the user points directly to http://localhost:3000 with POST verb?
You are posting to the root_url. Instead, POST your request to the items_url:
curl -d "number=100" http://localhost:3000/items
update:
Why the verb GET works on http://localhost:3000/?number=100 and the
same with http://localhost:3000/items/?number=100? Why the same does
not happens with POST?
The GET request to /?number=100 works because you have specified root 'items#index' in your routes file. This specifically creates a GET route that is mapped to the index action of the items controller.
How can I remove the message No route matches [POST] "/" if the user
points directly to http://localhost:3000 with POST verb?
You can create a single POST route using the post keyword:
# routes.rb
root 'items#index'
post '/', to: 'items#create'
which would generate the routes:
root GET / items#index
POST / items#create
(from your project directory run the command rails routes)
Or you can use the resource method to create all the CRUD paths:
resources :items, path: '/'
... which would create the following routes:
items GET / items#index
POST / items#create
new_item GET /new(.:format) items#new
edit_item GET /:id/edit(.:format) items#edit
item GET /:id(.:format) items#show
PATCH /:id(.:format) items#update
PUT /:id(.:format) items#update
DELETE /:id(.:format) items#destroy
Keep in mind that this may cause routing collisions if you try to add other resources to your app. If you need to add other resources, add them before these routes in the routes.rb file. Rails evaluates the routes file from top to bottom, so these resources would only load if no other paths match.
For more information see http://edgeguides.rubyonrails.org/routing.html

No route matches [POST] OmniAuth Steam Callback

I'm building Rails API for AngularJS app. I'm using devise_token_auth and omniauth-steam gems. When I try to authenticate user using the Steam there is an error:
ActionController::RoutingError (No route matches [POST] "/omniauth/steam/callback"
I've added devise_token_auth routes, but they don't create POST callbacks. I've tried to manually create POST route for callback, but it hasn't worked and I'm not sure if it is even correct solution. I'm trying to solve this problem from yesterday and I can't find anyone with the similar one.
config/routes.rb
Rails.application.routes.draw do
namespace 'api' do
namespace 'v1' do
mount_devise_token_auth_for 'Api::V1::User', at: 'auth'
end
end
end
config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :steam, ENV['steam_api_key']
end
I use figaro gem and save steam_api_key in application.yml file.
rake routes task
Prefix Verb URI Pattern Controller#Action
new_api_v1_api_v1_user_session GET /api/v1/auth/sign_in(.:format) devise_token_auth/sessions#new
api_v1_api_v1_user_session POST /api/v1/auth/sign_in(.:format) devise_token_auth/sessions#create
destroy_api_v1_api_v1_user_session DELETE /api/v1/auth/sign_out(.:format) devise_token_auth/sessions#destroy
api_v1_api_v1_user_password POST /api/v1/auth/password(.:format) devise_token_auth/passwords#create
new_api_v1_api_v1_user_password GET /api/v1/auth/password/new(.:format) devise_token_auth/passwords#new
edit_api_v1_api_v1_user_password GET /api/v1/auth/password/edit(.:format) devise_token_auth/passwords#edit
PATCH /api/v1/auth/password(.:format) devise_token_auth/passwords#update
PUT /api/v1/auth/password(.:format) devise_token_auth/passwords#update
cancel_api_v1_api_v1_user_registration GET /api/v1/auth/cancel(.:format) devise_token_auth/registrations#cancel
api_v1_api_v1_user_registration POST /api/v1/auth(.:format) devise_token_auth/registrations#create
new_api_v1_api_v1_user_registration GET /api/v1/auth/sign_up(.:format) devise_token_auth/registrations#new
edit_api_v1_api_v1_user_registration GET /api/v1/auth/edit(.:format) devise_token_auth/registrations#edit
PATCH /api/v1/auth(.:format) devise_token_auth/registrations#update
PUT /api/v1/auth(.:format) devise_token_auth/registrations#update
DELETE /api/v1/auth(.:format) devise_token_auth/registrations#destroy
api_v1_api_v1_user_confirmation POST /api/v1/auth/confirmation(.:format) devise_token_auth/confirmations#create
new_api_v1_api_v1_user_confirmation GET /api/v1/auth/confirmation/new(.:format) devise_token_auth/confirmations#new
GET /api/v1/auth/confirmation(.:format) devise_token_auth/confirmations#show
api_v1_auth_validate_token GET /api/v1/auth/validate_token(.:format) devise_token_auth/token_validations#validate_token
api_v1_auth_failure GET /api/v1/auth/failure(.:format) devise_token_auth/omniauth_callbacks#omniauth_failure
GET /api/v1/auth/:provider/callback(.:format) devise_token_auth/omniauth_callbacks#omniauth_success
GET /omniauth/:provider/callback(.:format) devise_token_auth/omniauth_callbacks#redirect_callbacks
omniauth_failure GET /omniauth/failure(.:format) devise_token_auth/omniauth_callbacks#omniauth_failure
GET /api/v1/auth/:provider(.:format) redirect(301)
I know that it's a bit messy because of namespaces, but it shouldn't cause this problem, right?
EDIT:
I did some research and here is the link https://github.com/lynndylanhurley/devise_token_auth#usage-tldr it says that /:provider/callback url should have GET/POST action, but as we can see I don't have POST action for callback.
Finally I've solved this problem by adding below line to the routes.rb file.
post '/omniauth/steam/callback', to: 'overrides/omniauth_callbacks#redirect_callbacks'
I've created omniauth_callbacks_controller.rb file in controllers/overrides folder and removed below line.
skip_before_action :set_user_by_token, raise: false
The last step was editing line with redirect route. I've changed this:
redirect_route = "#{request.protocol}#{request.host_with_port}/#{Devise.mappings[devise_mapping].fullpath}/#{params[:provider]}/callback"
To hard-coded route.
redirect_route = "/api/v1/auth/steam/callback"

How to run rails server with the rails api

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.

Circular Dependency Error autoloading constant

I keep getting the error "Circular dependency detected while autoloading constant API::V1::CitysController" when I try load my api page. Everything I've searched seems to suggest their might be a typo but I don't think there is one.
My routes:
namespace :api , defaults: {format: 'json'} do
namespace :v1 do
resources :citys
end
end
my controller is in app/controllers/api/v1/citys_controller.rb
Theres nothing in it really at the moment
class Api::V1::CitysController < ApplicationController
respond_to :json
def index
end
end
Not sure what else is relevant to the problem? It should just load a blank page without any errors when I go to localhost:3000/api/v1/citys
Added routes
Prefix Verb URI Pattern Controller#Action
pages_home GET /pages/home(.:format) pages#home
root GET / pages#home
api_v1_citys GET /api/v1/citys(.:format) api/v1/citys#index {:format=>"json"}
POST /api/v1/citys(.:format) api/v1/citys#create {:format=>"json"}
new_api_v1_city GET /api/v1/citys/new(.:format) api/v1/citys#new {:format=>"json"}
edit_api_v1_city GET /api/v1/citys/:id/edit(.:format) api/v1/citys#edit {:format=>"json"}
api_v1_city GET /api/v1/citys/:id(.:format) api/v1/citys#show {:format=>"json"}
PATCH /api/v1/citys/:id(.:format) api/v1/citys#update {:format=>"json"}
PUT /api/v1/citys/:id(.:format) api/v1/citys#update {:format=>"json"}
DELETE /api/v1/citys/:id(.:format) api/v1/citys#destroy {:format=>"json"}
I'm not sure why, but the error says it is looking for API::V1::CitysController class in your citys_controller.rb file and you have Api::V1::CitysController. So first and foremost change the name of your class to API::V1::CitysController (note the capitalized 'API'). That should solve your immediate problem.

Resources