По-сложно маршрутизиране на релси: ограничения

В момента, ако искате да добавите ограничение, има много начини да го направите, но както виждам в момента можете да включите само един окончателен метод, който се извиква. напр.

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/ }

Ако заявките бяха още по-сложни от това, нещата стават трудни. И така, има ли начин да добавите отделни методи вътре в клас, използван за ограничения?

По същество как се постига следното? Възможно ли е изобщо? Кой е най-добрият метод за използване на поддомейни в бял списък?

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?


person tsujp    schedule 08.02.2015    source източник


Отговори (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

ЗАБЕЛЕЖКА: Не проверих, че кодът работи, просто го написах наум, така че смятайте, че е по-скоро псевдо код, отколкото готова реализация.

Освен това можете да видите пример за тази техника, с някои повече подробности, на: Използвайте персонализирани ограничения за маршрутизиране, за да ограничите достъпа до Rails Routes чрез Warden.

person stevenharman    schedule 08.02.2015