New and Edit Routes missing in Rails Resources routes - ruby-on-rails

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

Related

Rails Routes: change resource identifier path name? always use params[:model_id] instead of params[:id]

I'm not sure how to ask this question...
But i'm working with nested ROUTES as shown below.
I like knowing that the Business ID can always be found using params[:business_id], obviously except for the actual business controller which requires me to use params[:id].
Is there a way to change the route resource id param to always be :business_id instead of having to be like Business.find(params.values_at(:business_id, :id).first)??
business_exports GET /businesses/:business_id/exports(.:format) businesses/exports#index
POST /businesses/:business_id/exports(.:format) businesses/exports#create
new_business_export GET /businesses/:business_id/exports/new(.:format) businesses/exports#new
edit_business_export GET /businesses/:business_id/exports/:id/edit(.:format) businesses/exports#edit
business_export GET /businesses/:business_id/exports/:id(.:format) businesses/exports#show
PATCH /businesses/:business_id/exports/:id(.:format) businesses/exports#update
PUT /businesses/:business_id/exports/:id(.:format) businesses/exports#update
DELETE /businesses/:business_id/exports/:id(.:format) businesses/exports#destroy
business_replenishments GET /businesses/:business_id/replenishments(.:format) businesses/replenishments#index
business_offer_prices GET /businesses/:business_id/offer_prices(.:format) businesses/offer_prices#index
POST /businesses/:business_id/offer_prices(.:format) businesses/offer_prices#create
business_unmatched_listings GET /businesses/:business_id/unmatched_listings(.:format) businesses/unmatched_listings#index
POST /businesses/:business_id/unmatched_listings(.:format) businesses/unmatched_listings#create
business_profit_loss_reports GET /businesses/:business_id/profit_loss_reports(.:format) businesses/profit_loss_reports#index
businesses GET /businesses(.:format) businesses#index
POST /businesses(.:format) businesses#create
new_business GET /businesses/new(.:format) businesses#new
edit_business GET /businesses/:id/edit(.:format) businesses#edit
business GET /businesses/:id(.:format) businesses#show
PATCH /businesses/:id(.:format) businesses#update
PUT /businesses/:id(.:format) businesses#update
DELETE /businesses/:id(.:format) businesses#destroy
If you're using Rails 4+ you can do this using the param option in the resources method
Overriding Route Parameters
Assuming you have code that looks like
resources :businesses
You can add an argument as such
resources :businesses, param: :business_id
Which should generate routes
businesses GET /businesses(.:format) businesses#index
POST /businesses(.:format) businesses#create
new_business GET /businesses/new(.:format) businesses#new
edit_business GET /businesses/:business_id/edit(.:format) businesses#edit
business GET /businesses/:business_id(.:format) businesses#show
PATCH /businesses/:business_id(.:format) businesses#update
PUT /businesses/:business_id(.:format) businesses#update
DELETE /businesses/:business_id(.:format)
UPDATE
Since you're generating these routes using the same nested resources you'll have to do the following
resources :businesses, param: :business_id
resources :businesses, only: [] do
resources :exports
...
end
A more clean way is to use the member
resources :businesses, param: :business_id do
member do
resources :exports
...
end
end

Api rails: no route matches

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

Rails: routes generated by hand have different prefix from those created with resources

I want to create rails routes by hand rather than using the automatic resource :tasks (it's just an exercise, I'll go back to the using resources :tasks once I understand this).
I /think/ that I have the right syntax, but the prefixes (path_helpers) generated when I write the routes by hand are wrong. Why, and what am I not doing properly?
Here is my code:
Rails.application.routes.draw do
root to: 'tasks#index'
get 'tasks', to: 'tasks#index'
get 'tasks/:id', to: 'tasks#show'
get 'tasks/new', to: 'tasks#new'
post 'tasks', to: 'tasks#create'
get 'tasks/:id/edit', to: 'tasks#edit'
patch 'tasks/:id', to: 'tasks#update'
delete 'tasks/:id', to: 'tasks#destroy'
end
Here are the routes & prefixes it creates when I call rails routes in my terminal:
Prefix Verb URI Pattern Controller#Action
root GET / tasks#index
tasks GET /tasks(.:format) tasks#index
GET /tasks/:id(.:format) tasks#show
tasks_new GET /tasks/new(.:format) tasks#new
POST /tasks(.:format) tasks#create
GET /tasks/:id/edit(.:format) tasks#edit
PATCH /tasks/:id(.:format) tasks#update
DELETE /tasks/:id(.:format) tasks#destroy
Here is what I get when I use resource :tasks
Prefix Verb URI Pattern Controller#Action
tasks GET /tasks(.:format) tasks#index
POST /tasks(.:format) tasks#create
new_task GET /tasks/new(.:format) tasks#new
edit_task GET /tasks/:id/edit(.:format) tasks#edit
task GET /tasks/:id(.:format) tasks#show
PATCH /tasks/:id(.:format) tasks#update
PUT /tasks/:id(.:format) tasks#update
DELETE /tasks/:id(.:format) tasks#destroy
EDIT:
To answer a few of the answers: I know that I can use 'as' to name the prefixes, but I think that I shouldn't have to in this case.
From what I understand, 'as' is only used in case you want to change the standard prefix to a personalized one, or if you think your routes might change in the future and you don't want to risk to mess with with your helpers. I should still get correct prefixes without using 'as'.
Here though, the prefix tasks_new with the get method is both linked to the tasks#new and tasks#edit methods, which I don't think is right.
Rails will let you name the routes. For example:
get 'tasks/new', to: 'tasks#new', as: :new_task
Use as for naming the route.
Write the code as following:
Rails.application.routes.draw do
root 'tasks#index'
get 'tasks' => 'tasks#index', as: 'task_list'
get 'tasks/:id' => 'tasks#show', as: 'display_task'
get 'tasks/new' => 'tasks#new', as: 'task_new'
post 'tasks' => 'tasks#create', as: 'task_create
get 'tasks/:id/edit' => 'tasks#edit', as: 'task_edit'
patch 'tasks/:id', to: 'tasks#update'
delete 'tasks/:id', to: 'tasks#destroy'
end

Administrate - Rails 4 | `add_route': Invalid route name, already in use: 'admin_root'

=> After deploying my rails app on Heroku
=> I cannot access to my admin at mysite.heroku.com/admin
--
I run heroku logs
The error : Invalid route name, already in use: 'admin_root'
/app/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/routing/route_set.rb:549:in `add_route': Invalid route name, already in use: 'admin_root' (ArgumentError)
And You may have defined two routes with the same name using the :as option
2016-10-24T13:43:56.930010+00:00 app[web.1]: You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with `resources` as explained here:
--
This is my config/routes.rb :
Rails.application.routes.draw do
root 'pages#index'
get '/agence' => 'pages#agence'
get '/methode' => 'pages#methode'
get 'projets' => 'projet#index'
get 'projets/:slug' => 'projet#show', as: 'projet'
get '/article' => 'article#index'
get '/article/:slug' => 'article#show', as: 'articles'
get '/contact' => 'pages#contact'
get '/mentionslegales' => 'pages#mentionslegales'
namespace :admin do
resources :projets
resources :articles
resources :users
# get '/' => 'projets#index'
root to: "projets#index"
end
if defined?(DashboardManifest)
namespace :admin do
DashboardManifest::DASHBOARDS.each do |dashboard_resource|
resources dashboard_resource
end
root controller: DashboardManifest::ROOT_DASHBOARD, action: :index
end
end
--
Rake routes :
Prefix Verb URI Pattern Controller#Action
root GET / pages#index
agence GET /agence(.:format) pages#agence
methode GET /methode(.:format) pages#methode
projets GET /projets(.:format) projet#index
projet GET /projets/:slug(.:format) projet#show
article GET /article(.:format) article#index
articles GET /article/:slug(.:format) article#show
contact GET /contact(.:format) pages#contact
mentionslegales GET /mentionslegales(.:format) pages#mentionslegales
admin_projets GET /admin/projets(.:format) admin/projets#index
POST /admin/projets(.:format) admin/projets#create
new_admin_projet GET /admin/projets/new(.:format) admin/projets#new
edit_admin_projet GET /admin/projets/:id/edit(.:format) admin/projets#edit
admin_projet GET /admin/projets/:id(.:format) admin/projets#show
PATCH /admin/projets/:id(.:format) admin/projets#update
PUT /admin/projets/:id(.:format) admin/projets#update
DELETE /admin/projets/:id(.:format) admin/projets#destroy
admin_articles GET /admin/articles(.:format) admin/articles#index
POST /admin/articles(.:format) admin/articles#create
new_admin_article GET /admin/articles/new(.:format) admin/articles#new
edit_admin_article GET /admin/articles/:id/edit(.:format) admin/articles#edit
admin_article GET /admin/articles/:id(.:format) admin/articles#show
PATCH /admin/articles/:id(.:format) admin/articles#update
PUT /admin/articles/:id(.:format) admin/articles#update
DELETE /admin/articles/:id(.:format) admin/articles#destroy
admin_users GET /admin/users(.:format) admin/users#index
POST /admin/users(.:format) admin/users#create
new_admin_user GET /admin/users/new(.:format) admin/users#new
edit_admin_user GET /admin/users/:id/edit(.:format) admin/users#edit
admin_user GET /admin/users/:id(.:format) admin/users#show
PATCH /admin/users/:id(.:format) admin/users#update
PUT /admin/users/:id(.:format) admin/users#update
DELETE /admin/users/:id(.:format) admin/users#destroy
admin_root GET /admin(.:format) admin/projets#index
I don't understand this error and how to resolve it.
I already read all posts about this error but can't find the solution..
Finally the solution was to with draw theses lines from routes.rb :
if defined?(DashboardManifest)
namespace :admin do
DashboardManifest::DASHBOARDS.each do |dashboard_resource|
resources dashboard_resource
end
root controller: DashboardManifest::ROOT_DASHBOARD, action: :index
end
end

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"

Resources