Routes in Rails with controllers that end in 's' - ruby-on-rails

This is just cosmetic but still driving me nuts. I've created a controller for my Address object and try to lay out routes for it. However, Rails seems to interpret the last 's' as plural and removes it from my paths, like this:
routes.rb:
resources :address
(note: this line is inside a namespace block called 'admin')
When I run rake routes I get this:
new_admin_addres
edit_admin_addres
... and so on. How do I get the extra 's' in my paths?

resources :addresses
which is the plural of address

Use the inflections to set address to be uncountable:
config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable %w( address )
end
This should now ignore any extra 's'. Not gramatically correct but should solve the issue.

Related

Rails routes: Wrong singular for resources

I have the following line in my routes.rb (Rails 4.1.4):
resources :request_caches
However, when I run rake routes I get the following output:
request_caches GET /request_caches(.:format) request_caches#index
POST /request_caches(.:format) request_caches#create
new_request_cach GET /request_caches/new(.:format) request_caches#new
edit_request_cach GET /request_caches/:id/edit(.:format) request_caches#edit
request_cach GET /request_caches/:id(.:format) request_caches#show
PATCH /request_caches/:id(.:format) request_caches#update
PUT /request_caches/:id(.:format) request_caches#update
DELETE /request_caches/:id(.:format) request_caches#destroy
As you can see, Rails somehow maps request_caches plural to request_cach singular. But it should be request_cache. Is this some kind of special case, because of the word caches? I've also played around with
resources :request_caches, as: :request_cache
But this results in wrong routes like request_cache_index. And furthermore, I think this is a standard task and should be solved clearly using Rails intern route helpers.
So, what am I doing wrong?
Rails guesses. It's not perfect. In config/initializers/inflections.rb add
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.irregular 'request_cache', 'request_caches'
end
You'll need to restart the server as it's in an initializer.
Have a look at config/initializers/inflections.rb. There should be some examples in the comments.
Something like this should do the trick:
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.singular 'request_caches' 'request_cache'
end
Be sure to restart the server after making changes to an initializer.
As I said,you can achieve it by changing config/initializers/inflections.rb like below
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.irregular 'request_cache', 'request_caches'
end

Rails 3.x How to properly define inflections

I have a need to define an inflection for the word 'chassis' where the same word defines both singular and plural and I am really struggling with this.
I thought I was there with the initialize/inflections.rb definition
ActiveSupport::Inflector.inflections do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
inflect.uncountable(/.*chassis.*/i)
end
Taking note of the example inflect.uncountable %w( fish sheep ) I tried to use inflect.uncountable %w( chassis ) when I first set up the scaffolding but that didn't work at all well as it didn't take into account leading parts in paths and caused problems with relationships and other tables like car_chassis and chassis_lookup.
Having looked at various solutions provided as answers to similar questions in Stack Overflow I eventually came up with inflect.uncountable(/.*chassis.*/i) Which seemed to take care of scaffolding but I'm having an issue with routes where <%= link_to "Chassis", admin_chassis_url%> gives me a no route for the show action error.
ActionController::RoutingError - No route matches {:action=>"show", :controller=>"admin/chassis"}
Which makes sense as I want the index action so I'm not passing an object to the path but Rails is obviously thinking I am requesting the show action
The other examples for regex's
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
are just complete gobbledygook to me and learning regular expressions needs a lifetime of learning that I neither have the inclination or the sanity to get my head round and the rails documentation http://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html on inflections is quite frankly pathetic.
I obviously haven't got the inflection right. Can anyone give me a complete solution as to exactly how I should define an inflection for the word "chassis" for me and for others please as none of the previous answers I've found provide a complete and proper solution
Your inflection seem to be correct.
Check what 'rake routes' tell you. In my case it was smart enough to detect that plural and single form of chassis was the same, so it generated admin_chassis_index instead of just admin_chassis for the #index action. Probably, the same is true for you. This is what I did:
In config/routes.rb
namespace :admin do
resources :chassis
end
Running 'rake routes' gives (note the first path):
admin_chassis_index GET /admin/chassis(.:format) admin/chassis#index
POST /admin/chassis(.:format) admin/chassis#create
new_admin_chassis GET /admin/chassis/new(.:format) admin/chassis#new
edit_admin_chassis GET /admin/chassis/:id/edit(.:format) admin/chassis#edit
admin_chassis GET /admin/chassis/:id(.:format) admin/chassis#show
PUT /admin/chassis/:id(.:format) admin/chassis#update
DELETE /admin/chassis/:id(.:format) admin/chassis#destroy
So, for #index I'd need to call:
<%= link_to "Chassis", admin_chassis_index_url%>

Rails3 Controllers Plural / Singular Routes

I have some issues with a controller in my rails3 application that is called nas
My ruby app is connected to an existing DB so the table name has to stay as nas.
In my models, I have previously been able to do this:
set_table_name
But I don't know how to do this in my controller / routes.
Right now, my routes contains this:
resources :nas
And the output is:
new_na GET /nas/new(.:format) {:action=>"new", :controller=>"nas"}
edit_na GET /nas/:id/edit(.:format) {:action=>"edit", :controller=>"nas"}
na GET /nas/:id(.:format) {:action=>"show", :controller=>"nas"}
PUT /nas/:id(.:format) {:action=>"update", :controller=>"nas"}
DELETE /nas/:id(.:format) {:action=>"destroy", :controller=>"nas"}
As you can see, rails drops the 's'
How can I resolve this?
Thanks
It's pretty confusing because I have no idea what a "na" or "nas" is. From your question I have the idea that you always want to refer to it as "nas", both plural and singular.
If that's the case, then the answer is to put this in config/initializers/inflections.rb:
ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable "nas"
end
This will also make your Nas model use the nas table by default, so no need for set_table_name.
However note that there is no reason to use Nas for your controllers if you don't want to! You can name them anything you like, as long as this is reflected in routes.rb and you use the correct model in your controller.
My ruby app is connected to an existing DB so the table name has to stay as nas.
Then why do your routes/controllers also have to be named nas? Once you fixed it on your model-level everything should be fine.
# model.rb
class WhateverILikeToCallMyModel
set_table_name "nas"
end
# controller.rb
class WaynesController << ApplicationController
# ...
def index
#items = WhateverILikeToCallMyModel.all
end
end
# routes.rb
resources :waynes
A guess, maybe you should try overriding the naming convention, because 'nas' is not plural? (assuming that's why the s dropped)
# Inflection rule
Inflector.inflections do |inflect|
inflect.irregular 'nas', 'nases'
end
in environment.rb
Edit: Instead of environment.rb use: config/initializers/inflections.rb (thanks Benoit Garret)
In your routes.rb, try,
match '/nas', :to => 'na'

Remove Routes Specified in a Gem?

Is there a way to remove routes specified in a gem in Rails 3? The exception logger gem specifies routes which I don't want. I need to specify constraints on the routes like so:
scope :constraints => {:subdomain => 'secure', :protocol => 'https'} do
collection do
post :query
post :destroy_all
get :feed
end
end
Based on the Rails Engine docs, I thought I could create a monkey patch and add a routes file with no routes specified to the paths["config/routes"].paths Array but the file doesn't get added to ExceptionLogger::Engine.paths["config/routes"].paths
File: config/initializers/exception_logger_hacks.rb
ExceptionLogger::Engine.paths["config/routes"].paths.unshift(File.expand_path(File.join(File.dirname(__FILE__), "exception_logger_routes.rb")))
Am I way off base here? Maybe there is a better way of doing this?
It is possible to prevent Rails from loading the routes of a specific gem, this way none of the gem routes are added, so you will have to add the ones you want manually:
Add an initializer in application.rb like this:
class Application < Rails::Application
...
initializer "myinitializer", :after => "add_routing_paths" do |app|
app.routes_reloader.paths.delete_if{ |path| path.include?("NAME_OF_GEM_GOES_HERE") }
end
Here's one way that's worked for me.
It doesn't "remove" routes but lets you take control of where they match. You probably want every route requested to match something, even if it is a catch all 404 at the bottom.
Your application routes (MyApp/config/routes.rb) will be loaded first (unless you've modified the default load process). And routes matched first will take precedence.
So you could redefine the routes you want to block explicitely, or block them with a catch all route at the bottom of YourApp/config/routes.rb file.
Named routes, unfortunately, seem to follow ruby's "last definition wins" rule. So if the routes are named and your app or the engine uses those names, you need to define the routes both first (so yours match first), and last (so named routes point as you intended, not as the engine defines.)
To redefine the engine's routes after the engine adds them, create a file called something like
# config/named_routes_overrides.rb
Rails.application.routes.draw do
# put your named routes here, which you also included in config/routes.rb
end
# config/application.rb
class Application < Rails::Application
# ...
initializer 'add named route overrides' do |app|
app.routes_reloader.paths << File.expand_path('../named_routes_overrides.rb',__FILE__)
# this seems to cause these extra routes to be loaded last, so they will define named routes last.
end
end
You can test this routing sandwich in the console:
> Rails.application.routes.url_helpers.my_named_route_path
=> # before your fix, this will be the engine's named route, since it was defined last.
> Rails.application.routes.recognize_path("/route/you/want/to/stop/gem/from/controlling")
=> # before your fix, this will route to the controller and method you defined, rather than what the engine defined, because your route comes first.
After your fix, these calls should match each other.
(I posted this originally on the refinery gem google group here: https://groups.google.com/forum/?fromgroups#!topic/refinery-cms/N5F-Insm9co)

Rails 3 routing: singular option

You used to be able to do:
resources :paises, :singular => :pais
But I tried this in Rails and it didn't work. I want to have 'pais_path()' for show and 'paises_path()' for index.
thanks
open your config/initializers/inflections.rb file and add this
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'pais', 'paises'
end
then your route resources :paises will work for you as expected

Resources