Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
690 views
in Technique[技术] by (71.8m points)

ruby on rails - Creating routes with an optional path prefix

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...