Constraints in Rails Router

Add validations while customizing Rails Router

Tushar Adhao
3 min readNov 20, 2019

The next step to customizing router is to dig a li’l deep down into the Rails Router where we can find some features like ‘Constraints’. So basically, there are some security check features available too in the Rails Router through which not only the code gets optimized along with the appearance and workflow looks neat and clean but also it gets secured as per the desired requirements. There are many use cases for Constraints and few of them are discussed in this section.

Let’s restrict IP addresses accessing our Rails application and allow some IP’s using ‘Constraints’. So basically, there are two ways to do it, one of them is simply defining conditions in the routes.rb file as below,

config/routes.rbRails.application.routes.draw do
constraints(ip: /127\.0\.0\.1$/) do
resources :homes
end
end

This code will restrict all IP’s to access ‘homes’ route except the IP => 127.0.0.1 . So the pages associated with the route will not be accessible to any other IPs, hence to perform the desired operation. Now the other way to do the same operation but including ‘class’ / ‘model’ to make it more dynamic can be given as,

config/routes.rbRails.application.routes.draw do
constraints Home.new do
resources :homes
end
end

Now as per the code, the Home.new will initialize an object for Home class and that’s where we can put conditions to restrict it using the route as below,

app/models/home.rbclass Home < ActiveRecord::Base  def initialize
@domains = [‘127.0.0.1’, ‘203.123.10.1’]
end
def matches?(request)
@domains.include? request.remote_ip
end
end

So this code will work in the following manner as, whenever a URL related to route home will get a hit on the browser, the condition for initializing home object will be checked in which some IP’s are defined, then it will check if the IP is in the available IP list in the ‘matches method and return either true or false depending on the result, hence to perform the desired operation for restricting other IP’s.

Now, let’s see what else this ‘Constraints’ can do along with checking out for condition like IP’s.

config/routes.rbRails.application.routes.draw do
resources :homes
get ‘homes/:id/reviews’ => ‘homes#reviews’, as: :reviews, constraints: { id: /\d+/ }
end

This will restrict the id field for the review route to have an only numeric value. So for any non-numeric value, the route will not be accessible. Similarly, ‘Constraints’ can be used to restrict the field to have string value as, constraints: { id: /[A-Za-z]+/ } .

The use case for ‘Constraints’ also includes restricting fields like subdomain for some routes.

config/routes.rbRails.application.routes.draw do
constraints subdomain: ‘org2’ do
resources :homes
end
end

In the code above, the route related to homes will be accessible for only subdomain org2’ and not for any other subdomain. The general use case for subdomain restriction is within any multi-tenant Rails application.

There are many more features of using constraints like restricting format as, constraints: { format: ‘json’ } and so on, which also depends on the various scenarios associated.

--

--

Tushar Adhao

Software artist spreading nuggets of coding gold and sometimes philosophy too.