ruby 48 lines · 8 steps

How routing constraints gate admin routes in Rails

A constraint object lets Rails match a route only when the current request comes from a logged-in admin.

Explained by highlit
1class AdminConstraint
2 def self.matches?(request)
3 new(request).matches?
4 end
5 
6 def initialize(request)
7 @request = request
8 end
9 
10 def matches?
11 user = current_user
12 user.present? && user.admin?
13 end
14 
15 private
16 
17 attr_reader :request
18 
19 def current_user
20 return unless user_id = warden&.user&.id || session_user_id
21 
22 User.find_by(id: user_id)
23 end
24 
25 def warden
26 request.env["warden"]
27 end
28 
29 def session_user_id
30 request.session[:user_id]
31 end
32end
33 
34Rails.application.routes.draw do
35 constraints(AdminConstraint) do
36 namespace :admin do
37 root to: "dashboard#show"
38 
39 resources :users, only: %i[index show update]
40 resources :reports, only: %i[index show]
41 resource :settings, only: %i[show update]
42 
43 mount Sidekiq::Web => "/sidekiq"
44 end
45 end
46 
47 match "/admin/*path", to: "errors#not_found", via: :all
48end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Route constraints decide matching before a controller ever runs, keeping authorization out of every admin action.
  2. 2Implementing self.matches? lets a plain class act as a constraint while keeping per-request state in an instance.
  3. 3A catch-all fallback route hides admin paths from non-admins by returning not-found instead of leaking a redirect.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How routing constraints gate admin routes in Rails — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code