Creating routes with an optional path prefix Creating routes with an optional path prefix ruby ruby

Creating routes with an optional path prefix


OK, I've managed to sort out this problem:

THere is no way of doing this in Rails by default (at least, not yet). Instead of using namespaces and default values, I needed to install Sven Fuchs' routing filter.

Once the plugin is installed, I added the following file to my lib directory:

require 'routing_filter/base'module RoutingFilter  class Locale < Base    # remove the locale from the beginning of the path, pass the path    # to the given block and set it to the resulting params hash    def around_recognize(path, env, &block)      locale = nil      path.sub! %r(^/([a-zA-Z]{2})(?=/|$)) do locale = $1; '' end      returning yield do |params|        params[:locale] = locale || 'en'      end    end    def around_generate(*args, &block)      locale = args.extract_options!.delete(:locale) || 'en'      returning yield do |result|        if locale != 'en'          result.sub!(%r(^(http.?://[^/]*)?(.*))){ "#{$1}/#{locale}#{$2}" }        end       end    end  endend

I added this line to routes.rb:

map.filter 'locale'

This basically fills out a before and after hook, generated by the plugin, that wraps the rails routing.

When a url is recognised, and before Rails gets to do anything with it, the around_recognize method is called. This will extract a two-letter code representing the locale, and pass it through in the params, defaulting to 'en' if no locale is specified.

Likewise, when a url is generated, the locale parameter will be pushed into the URL on the left side.

This gives me the following urls and mappings:

/   => :locale => 'en'/en => :locale => 'en'/fr => :locale => 'fr'

All existing url helpers work as before, with the only difference being that unless the locale is specified, it is preserved:

home_path                  => /home_path(:locale => 'en') => /home_path(:locale => 'fr') => /fr


You can define defaults in a route using the :defaults key. Try this:

map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show',                               :defaults => { :lang => 'en' }


I understand that this old question, but it may be useful.

  map.with_options(:path_prefix => ":locale") do |m|    m.resources :posts    m.resources :stories          end

And you have to add before filter to application controller to define locale, such as

before_filter :define_localedef define_locale  if params[:locale] == nil    I18n.locale = 'en'  else    I18n.locale = params[:locale]  endend