Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating routes with an optional path prefix

Tags:

How can I go about making my routes recognise an optional prefix parameter as follows:

/*lang/controller/id 

In that the lang part is optional, and has a default value if it's not specified in the URL:

/en/posts/1   => lang = en /fr/posts/1   => lang = fr /posts/1      => lang = en 

EDIT

Ideally, I'm looking to do this across many controllers and actions by mapping a namespace:

map.namespace "*lang" do |lang|   lang.resources :posts   lang.resources :stories end 
like image 587
Codebeef Avatar asked Oct 17 '08 14:10

Codebeef


People also ask

Which character lets us create optional route params?

Basically, you can use the ? character to make the parameter optional.

How do you pass optional parameter in URL in react?

You use parenthesis ( ) to wrap the optional parts of route, including the leading slash ( / ). Check out the Route Matching Guide page of the official documentation. Note: The :paramName parameter matches a URL segment up to the next / , ? , or # . For more about paths and params specifically, read more here.

What is root route in rails?

root 'topics#index' is a Rails route that says the default address for your site is topics#index . topics#index is the topics list page (the topics controller with the index action). Rails routes control how URLs (web addresses) get matched with code on the server.


1 Answers

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    end end 

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 
like image 132
Codebeef Avatar answered Sep 29 '22 06:09

Codebeef