写在前面:在看 devise 的源码过程中,发现 Devise 在做 Routes Mapping 时,使用了 Rails 自己的@constraints。于是查查文档,笔记两件事。
以下内容粗略翻译自 Ruby on Rails 4.0.1,ActionDispatch::Routing::Mapper::Scoping。
位置:actionpack/lib/action_dispatch/routing/mapper.rb
这种写法很熟悉的。
namespace "admin" do
resources :posts, :comments
end
那么,访问/posts
,调用 Admin::PostsController
时,如何写呢?
scope module: "admin" do
resources :posts
end
或者
resources :posts, module: "admin"
当然,反过来,访问 /admin/posts
时,调用 PostsController
,就这么写:
scope "/admin" do
resources :posts
end
或者
resources :posts, path: "/admin/posts"
比如允许 /posts/1.1
访问,而禁止 /posts/1
,那么代码如下:
constraints(id: /\d+\.\d+/) do
resources :posts
end
在其他的资源引用上,也可以做如下限制:
resources :posts do
constraints(post_id: /\d+\.\d+/) do
resources :comments
end
end
限制 ip 访问,比如 只允许 192.168.* 访问资源:
constraints(ip: /192\.168\.\d+\.\d+/) do
resources :posts
end
动态请求时的匹配,比如下面的这个限制:
constraints(lambda { |req| req.env["HTTP_USER_AGENT"] =~ /iPhone/ }) do
resources :iphones
end
当然你也可以把它放到 model 里:
class Iphone
def self.matches?(request)
request.env["HTTP_USER_AGENT"] =~ /iPhone/
end
end
下面这句话有待验证,暂时不译:
An expected place for this code would be lib/constraints.
This class is then used like this:
constraints(Iphone) do
resources :iphones
end
好了,笔记结束,也结束一天的事情,今天的小聚会很开心,聊了很多。
里克,2013 年 11 月 3 日,晚。