Post

Rails Routing Constraints

Rails Routing Constraints

title: “Constraints de roteamento no Rails” date: 2021-04-05 09:00:20 +0300 categories: rails routing tags: rails routing constraints —-

Quando usar routing constraints no Rails

Constraints permitem ao roteador decidir para onde enviar a request sem empurrar a lógica para controllers. Útil para roteamento por subdomínio, home diferente para guest/logado, controle de formato e proxys.

Abordagem base (controller)

Você pode redirecionar no controller, mas o router continua fazendo trabalho extra:

1
2
3
4
5
6
7
8
9
10
11
12
# app/controllers/home_controller.rb
class HomeController < ApplicationController
  before_action :redirect_to_dashboard_if_signed_in

  def index; end

  private

  def redirect_to_dashboard_if_signed_in
    redirect_to dashboard_path if signed_in?
  end
end
1
2
3
4
5
# config/routes.rb
Rails.application.routes.draw do
  resource :dashboard, only: [:index]
  resource :home, only: [:index]
end

Use routing constraints

Mantenha decisões em routes.rb. Padrões comuns:

  1. Constraint por segmento
    1
    2
    
    match '/:year/:month/:day' => 'info#about',
      constraints: { year: /\d{4}/, month: /\d{2}/, day: /\d{2}/ }
    
  2. Constraint por request (User-Agent, subdomínio, formato)
    1
    2
    
    match '/:year/:month/:day' => 'info#about',
      constraints: { user_agent: /Firefox/ }
    
  3. Constraint dinâmica (lambda ou classe)
    • Lambda:
      1
      2
      
      get '*path', to: 'proxy#index',
      constraints: ->(req) { req.env['SERVER_NAME'].match?('foo.bar') }
      
    • Class: ```ruby constraints Subdomain do get ‘*path’, to: ‘proxy#index’ end

class Subdomain def self.matches?(request) request.subdomain.present? && request.subdomain.start_with?(‘foobar’) end end

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
### Exemplo: home para guest vs logado

```ruby
# lib/signed_in_home.rb
class SignedInHome
  def self.matches?(request)
    request.cookies['remember_token'].present?
  end
end

# config/routes.rb
Rails.application.routes.draw do
  constraints SignedInHome do
    root to: 'dashboard#show', as: :dashboard
  end

  root to: 'home#show'
end

Aqui o router decide qual root servir antes de chegar ao controller. Troque a lógica do cookie pelo seu mecanismo de auth (ex.: Warden, JWT etc.).

Nota: há 2 rotas para root, uma dentro do constraint e outra fora. A ordem importa.

Esta postagem está licenciada sob CC BY 4.0 pelo autor.