2015-02-08 132 views
0

当前如果你想添加一个约束,有许多方法可以做到这一点,但正如我目前所看到的,你只能包含一个被调用的权威方法。例如。Rails路由更复杂:约束

Class Subdomain 

    # Possible other `def`s here, but it's self.matches? that gets called. 

    def self.matches?(request) 
    # Typical subdomain check here 
    request.subdomain.present? && request.subdomain != "www" 
    end 

end 

与上面的方法是它不处理在WWW前缀的路由问题,那就是管理和www.admin是indistuingishable。可以添加更多逻辑,但是如果需要通过一组静态子域名(例如admin,support和api),则需要制作SubdomainAdmin,SubdomainSupport等....

这可以用正则表达式解决,如下所示: routes.rb

管理

:constraints => { :subdomain => /(www.)?admin/ } 

API

:constraints => { :subdomain => /(www.)?api/ } 

如果要求甚至比这件事更复杂得招年。那么有没有办法在用于约束的类中添加单个方法?

本质上,下面是如何实现的?它甚至有可能吗?什么是白名单子域名使用的最佳方法?

E.g.

Class Subdomain 

    def self.admin_constraint(request) 
    # Some logic specifically for admin, possible calls to a shared method above. 
    # We could check splits `request.subdomain.split(".")[ 1 ].blank?` to see if things are prefixed with "www" etc.... 
    end 

    def self.api_constraint(request) 
    # Some logic specifically for api, possibly calls to a shared method above. 
    # We could check splits `request.subdomain.split(".")[ 1 ].blank?` to see if things are prefixed with "www" etc.... 
    end 

    def self.matches?(request) 
    # Catch for normal requests. 
    end 

end 

,使我们现在能够专门致电限制如下:

:constraints => Subdomain.admin_constraints 

而且所有通用的约束如下:

:constraints => Subdomain 

这可能对Rails 4.0.3?

回答

0

路由器会在您通过路由的任何对象上调用#matches?(request)方法。在

:constraints => Subdomain 

您正在给路由Subdomain Class对象。但是,您也可以传递一个实例,您可以通过参数进行配置。例如,

Class Subdomain 
    def initialize(pattern) 
    @pattern = pattern 
    end 

    def matches?(request) 
    request.subdomain.present? && @pattern ~= request.subdomain 
    end 
end 

# routes.rb 

namespace :admin, constraints: Subdomain.new(/(www.)?admin/) do 
    # your admin routes here. 
end 

注:我没有验证码的作品,我只是写了我的头顶部,所以认为不是实施准备更加的伪代码。

此外,你可以看到一个这种技术的例子,更多的细节,在:Use custom Routing Constraints to limit access to Rails Routes via Warden