【问题标题】:Rails routing more complex :constraintsRails 路由更复杂:constraints
【发布时间】:2025-12-06 01:05:02
【问题描述】:

目前,如果您希望添加约束,有很多方法可以做到这一点,但正如我所见,目前您只能包含一个被调用的确定方法。例如

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 为前缀的路由,即 admin 和 www.admin 无法区分。可以添加更多逻辑,但如果需要在一组静态子域(如 admin、support 和 api)上执行此操作,您当前需要创建 SubdomainAdmin、SubdomainSupport 等......

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

管理员

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

API

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

如果请求比这更复杂,事情就会变得棘手。那么有没有办法在用于约束的类中添加单独的方法?

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

例如

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 中可行吗?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4


    【解决方案1】:

    路由器将在您传递路由的任何对象上调用#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 上查看此技术的示例以及更多详细信息。

    【讨论】: