Rails 3 route has incorrect singular form - ruby-on-rails

I have the following routes:
resources :businesses, only: [:show, :index, :new, :create] do
resources :pledge_drives
end
This creates the following:
% rake routes | grep pledge
business_pledge_drives GET /businesses/:business_id/pledge_drives(.:format) pledge_drives#index
POST /businesses/:business_id/pledge_drives(.:format) pledge_drives#create
new_business_pledge_drife GET /businesses/:business_id/pledge_drives/new(.:format) pledge_drives#new
edit_business_pledge_drife GET /businesses/:business_id/pledge_drives/:id/edit(.:format) pledge_drives#edit
business_pledge_drife GET /businesses/:business_id/pledge_drives/:id(.:format) pledge_drives#show
PUT /businesses/:business_id/pledge_drives/:id(.:format) pledge_drives#update
DELETE /businesses/:business_id/pledge_drives/:id(.:format) pledge_drives#destroy
I do not want the URL helper method to be called business_pledge_drife_path. How can I correct Rails in its singularization of drives? The actual URLs are fine.
Edit: this answer got it right. I added the following to config/initializers/inflections.rb:
ActiveSupport::Inflector.inflections do |inflect|
inflect.plural 'drive', 'drives'
inflect.singular 'drives', 'drive'
end
Now my routes are:
business_pledge_drives GET /businesses/:business_id/pledge_drives(.:format) pledge_drives#index
POST /businesses/:business_id/pledge_drives(.:format) pledge_drives#create
new_business_pledge_drive GET /businesses/:business_id/pledge_drives/new(.:format) pledge_drives#new
edit_business_pledge_drive GET /businesses/:business_id/pledge_drives/:id/edit(.:format) pledge_drives#edit
business_pledge_drive GET /businesses/:business_id/pledge_drives/:id(.:format) pledge_drives#show
PUT /businesses/:business_id/pledge_drives/:id(.:format) pledge_drives#update
DELETE /businesses/:business_id/pledge_drives/:id(.:format) pledge_drives#destroy

Most of the time, rails knows about the correct pluralizations of the words, e.g: model name.
However, In other cases, You can define correct conversions in rails using Inflections.

Related

How to shorten a url helper in rails

There are a lot of SO questions on this but none of them was able to answer what I was looking for. Please let me know if I am wrong.
I have following routes in my route files
namespace :integrations do
resources :google, only: [] do
collection do
get 'prompt'
get 'callback'
end
end
end
These creates very long url helpers like below.
prompt_integrations_google_index GET /integrations/google/prompt(.:format) integrations/google#prompt
callback_integrations_google_index GET /integrations/google/callback(.:format) integrations/google#callback
I've tried using as but that doesn't work. I don't know if using path is the right way. How can I shorten their helper name?
Ex:
google_prompt_integrations_google_index -> google_prompt
I would like to do the renaming for just one selected route and keep all others unchanged.
You can write the route definition as:
namespace :integrations, as: '' do
resource :google, only: [] do
collection do
get 'prompt'
get 'callback'
end
end
end
And then add the below inflections to remove _index with helper. _index comes from this implementation
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.plural /^(google)$/i, '\1s'
inflect.singular /^(google)s/i, '\1'
end
Now you get as you want:
$ rails routes | grep google
prompt_google GET /integrations/google/prompt(.:format) integrations/googles#prompt
callback_google GET /integrations/google/callback(.:format) integrations/googles#callback
Have you tried this way with as
namespace :integrations, as: '' do
resource :google, only: [:prompt, :callback] do
collection do
get 'prompt', as: 'prompt'
get 'callback', as: 'cb'
end
end
end
On rake routes we get prompt_google and cb_google
#rake routes
prompt_google GET /integrations/google/prompt(.:format) integrations/googles#prompt
cb_google GET /integrations/google/callback(.:format) integrations/googles#callback
Update:
In the case you want to just change 1 route why not have something like
get 'integrations/google/prompt', to: 'integrations/google#prompt', as: 'google_prompt'
rake routes will return
google_prompt GET /integrations/google/prompt(.:format) integrations/google#prompt

Why does order matter in Rails routes.rb when using resources?

I receive an error when my route is listed as such:
resources :coupons
get 'coupons/redeem_coupon', to: 'coupons#redeem_coupon', as: 'redeem_coupon'
The error is:
ActiveRecord::RecordNotFound - Couldn't find Coupon with 'id'=redeem_coupon:
When I reverse the order to:
get 'coupons/redeem_coupon', to: 'coupons#redeem_coupon', as: 'redeem_coupon'
resources :coupons
It works fine. I understand that resources creates these routes
GET /coupons
GET /coupons/new
POST /coupons
GET /coupons/:id
GET /coupons/:id/edit
PATCH/PUT /coupons/:id
DELETE /coupons/:id
Is listing my custom route first, more specific or overriding the other route? Why does the order matter?
The error you're getting is because rails tries to match routes starting from the top down. If you're trying to add a custom route to an existing resource, the easier way is to do this. collection is if you want to use it on the group, member is if you want to add a custom route to an individual resource.
resources :coupons do
collection do
get 'redeem_coupon'
end
end
By listing your custom route first, you are overriding the other route. When rails gets a request, it simply starts from the top of your routes.rb file and goes with whichever route matches first.

Rails routing: uninitialized constant ClanController

I have some problems with routing custom controller actions
Routes:
resources :clans do
get 'leave' =>'clan#leave_clan'
get 'dismiss' =>'clan#dismiss_clan'
get 'kick_from_clan/:user_id' =>'clan#kick'
get 'invite/:user_id' =>'clan#invite'
get 'join' =>'clan#join'
end
namespace :admin do
resources :clans
resources :users
end
I know i have clans both in admin namespace and also without but that is how i need it, actions are completely different in them.
And I use a generated route as clan_join_path(clan).
This action results in the next error:
uninitialized constant ClanController
Directory structure:
/app
/controller
/admin
/ClansController.rb
/ClansController.rb
EDIT:
Also invite and kick routes are not generated as expected.
*no path* GET /clans/:clan_id/kick_from_clan/:user_id(.:format) clan#kick
*no path* GET /clans/:clan_id/invite/:user_id(.:format) clan#invite
Any suggestion to the edit part?
You're defining a resource called clans and I presume you have a controller also called ClansController (note the puralization). If you don't have this controller, you'll be wanting to create it.
You probably therefore need to pluralize your routes:
resources :clans do
get 'leave' =>'clans#leave_clan'
get 'dismiss' =>'clans#dismiss_clan'
get 'kick_from_clan/:user_id' =>'clans#kick'
get 'invite/:user_id' =>'clans#invite'
get 'join' =>'clans#join'
end
Also make sure your controller is named clans_controller.rb (pluralized).
You can use member do ... end to properly route based on type of action
resources :clans do
member do
get :leave
get :dismiss
#etc
end
end
This will define the routes as clans/:id/leave clans/:id/dismiss
Check if your clans_controller.rb is intentionally not plural.
resources :clans do
get 'leave' =>'clans#leave_clan'
get 'dismiss' =>'clans#dismiss_clan'
get 'kick_from_clan/:user_id' =>'clans#kick'
get 'invite/:user_id' =>'clans#invite'
get 'join' =>'clans#join'
end
app/controllers/clans_controller.rb
class ClansController < ApplicationController
end

ActiveRecord::RecordNotFound in ContactsController#create Couldn't find Company without an ID error

When i try to submit at localhost:3000/companies/1/contacts/new i get the error Couldn't find Company without an ID https://gist.github.com/overhang/f8c20d2d2c851cdee7b1 any clue?
I reckon it might be a problem with routes.rb
Remove the following lines from routes.rb
# config/routes.rb
# get "companies/index"
# get "companies/new"
# get "companies/show"
# get "companies/create"
# get "companies/edit"
Notice that RESTful controller actions like edit and show require a specific Company passed in order for the correct company to be looked up. These get routes don't allow for that. Instead, you should be utilizing the resource routes you've already created:
# config/routes.rb
resources :companies
The non-resourceful routes are impeding the execution of the resourceful ones. Removing them should fix your problem.

Rails 3 routing inside a controller

I have just switched to rails from padrino/sinatra so the routing stuff puzzles me.
I have defined,
namespace :admin do
resources :teachers, :students, :lessons
end
in my routes.rb file, and when i run rake routes command it gives me,
admin_teachers GET /admin/teachers(.:format) admin/teachers#index
POST /admin/teachers(.:format) admin/teachers#create
new_admin_teacher GET /admin/teachers/new(.:format) admin/teachers#new
edit_admin_teacher GET /admin/teachers/:id/edit(.:format) admin/teachers#edit
admin_teacher GET /admin/teachers/:id(.:format) admin/teachers#show
PUT /admin/teachers/:id(.:format) admin/teachers#update
DELETE /admin/teachers/:id(.:format) admin/teachers#destroy
admin_students GET /admin/students(.:format) admin/students#index
POST /admin/students(.:format) admin/students#create
new_admin_student GET /admin/students/new(.:format) admin/students#new
edit_admin_student GET /admin/students/:id/edit(.:format) admin/students#edit
admin_student GET /admin/students/:id(.:format) admin/students#show
PUT /admin/students/:id(.:format) admin/students#update
DELETE /admin/students/:id(.:format) admin/students#destroy
admin_lessons GET /admin/lessons(.:format) admin/lessons#index
POST /admin/lessons(.:format) admin/lessons#create
new_admin_lesson GET /admin/lessons/new(.:format) admin/lessons#new
edit_admin_lesson GET /admin/lessons/:id/edit(.:format) admin/lessons#edit
admin_lesson GET /admin/lessons/:id(.:format) admin/lessons#show
PUT /admin/lessons/:id(.:format) admin/lessons#update
DELETE /admin/lessons/:id(.:format) admin/lessons#destroy
The problem is, i can't figure out how to respond a request to admin/students#update? I know how to respond to admin#teachers, in my admin controller i create a teachers function. But how to respond to admin/teachers/index? Or maybe where to respond? In which file? In which function or class?
For admin/students#update Rails will look for the action here:
class Admin::StudentsController < ApplicationController
def update
# update here
end
end
You can generate this file with:
rails generate controller admin/students update
Which will write to:
app/controllers/admin/students_controller.rb

Resources