Rails路由约束和UTF-8

mu *_*ort 9 routing ruby-on-rails utf-8 ruby-on-rails-3

我需要处理像这样的路线/:slug.slu to被限制在其他地方以匹配:

\A[\p{Alnum}_.-]{3,}\z
Run Code Online (Sandbox Code Playgroud)

明显的路线:

get '/:slug' => '...', :constraints => { :slug => /[\p{Alnum}_.-]{3,}/ }
get '/:slug' => '...', :slug => /[\p{Alnum}_.-]{3,}/
Run Code Online (Sandbox Code Playgroud)

做工精细用ASCII网址,像/mu-is-too-short/where.is.pancakes.house,但一切都分崩离析当URL是/µ-is-too-short.浏览器将其发送到服务器:

/%C2%B5-is-too-short
Run Code Online (Sandbox Code Playgroud)

和Rails试图检查编码%C2%B5-is-too-short:slug约束和失败,因为%不是\p{Alnum}.

我想出了两个克拉奇:

get '/:slug' => '...', :slug => /.{3,}/
get '/:slug' => '...', :slug => /[^\/]+/, :constraints => lambda { |r| r.path_parameters[:slug].to_s =~ /\A[\p{Alnum}_.-]{3,}\z/ }
Run Code Online (Sandbox Code Playgroud)

:slug => /[^\/]+/在第二个是需要保持从Rails的以为.ba.b为一个格式扩展名.

有没有办法让Rails表现得合理并:slug根据约束检查解码,还是我必须放松约束或手工完成?

Hou*_*uen 0

您可以使用 lambda 作为约束,并通过这种方式更改编码(来自http://www.intridea.com/blog/2011/2/21/use-lambdas-for-rails3-route-constraints):

scope :constraints => lambda{|req| !req.session[:user_id].blank? } do
  # all my logged in routes
end
Run Code Online (Sandbox Code Playgroud)