Environment specific routing in rails
For better application support, it is usually nice to build features that allow us query live system information inside a webapp. Such information can obviously be password protected. However, recently I ended up in a situation where client wasn’t ready to reveal such information in production environment. So, I had to disable this functionality in production.
In rails, this means disabling certain routes for production environment. It isn’t a major problem since you can guard your route declarations using RAILS_ENV value. However, I ran into a few quirks that I had to resolve.
In my case, my debug resources were available at URI ‘/debug’ (that went to DebugController as is usually the case). My routes.rb contained
ActionController::Routing::Routes.draw do |map| ... map.resources :debug ... end
This obviously allows /debug for all environments. For disabling it in production, I did this:
map.resources :debug unless RAILS_ENV == 'production'
This didn’t work. The reason was my routes still had the default routes:
ActionController::Routing::Routes.draw do |map| ... map.resources :debug ... # Install the default routes as the lowest priority. # Note: These default routes make all actions in every controller accessible via GET requests. You should # consider removing or commenting them out if you're using named routes and resources. map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end
As the comments suggest, these routes should ideally be removed in RESTful app. However, in my project, that may mean several broken routes. That was more then what I wanted to handle at this time. So, my options were to add another route for production before these default routes that would send the user to some default message with proper flash message. Here is what I ended up with:
map.debug "debug", :controller => "debug", :action => "noop" if RAILS_ENV == 'production' map.resources :debug unless RAILS_ENV == 'production'
and
class DebugController < ApplicationController ... def noop flash[:message] = "Debug information is not available in this environment" redirect_to root_url end end
With this, all /debug/* got sent to action “noop” in production environment. I could test routes using “rake routes” command by setting environment variable RAILS_ENV to “development” vs. “production”.
$ export RAILS_ENV=development $ rake routes | grep debug debug_index GET /debug(.:format) {:controller=>"debug", :action=>"index"} POST /debug(.:format) {:controller=>"debug", :action=>"create"} new_debug GET /debug/new(.:format) {:controller=>"debug", :action=>"new"} edit_debug GET /debug/:id/edit(.:format) {:controller=>"debug", :action=>"edit"} debug GET /debug/:id(.:format) {:controller=>"debug", :action=>"show"} PUT /debug/:id(.:format) {:controller=>"debug", :action=>"update"} DELETE /debug/:id(.:format) {:controller=>"debug", :action=>"destroy"} $ export RAILS_ENV=production $ rake routes | grep debug debug /debug {:controller=>"debug", :action=>"noop"}
For TDD, this could be unit tested as described here.
No related posts.
Related posts brought to you by Yet Another Related Posts Plugin.





