← Back to blog
· 3 min read · routes rails ruby

Rails Routing Constraints

Routing is backbone of a web applications. When we are building applications using Rails we can manage routing for our app easily. I am going to explain a bit advance feature of routing in Rails

What is routing constraints

Few many times we require routes to behave differently and also want to do some routing based on specific conditions.

For example

  • Constraint routes for http methods( put, post )

  • Want to show different home page for different users.

  • Want to restrict URL for some sub domain or range of IP addresses

We can easily constraints our routes in Rails

How many ways we can constraint our routes

Segment Constraints(Parameter Restriction)

You can filter any parameter based on Regular expression <!--more-->

Lets say we have route

resources :maps

If we want to restrict it for certain range of IP addresses we can do like

    resources :maps, constraints: { ip: /172\.124\.\d+\.\d+/ }

OR

    constraints( ip: /172\.124\.\d+\.\d+/) do
      resources :maps
    end

Another example of filtering id parameter

    match 'maps/:id', to: 'maps#show' ,constraints: { id: /\d+/}, via: :get

Now URL with id as integer only allowed to hit maps#show action

Can restrict format parameter

    match 'maps/:id', to: 'maps#show' ,constraints: { format: 'json' }, via: :get

It will generate route only for json format so if somebody try to open HTML format for this URL it won't hit maps show action.

Request-Based Constraints

We can also constraint routes on request object

    get 'admin/', to: 'admin#show', constraints: { subdomain: 'admin' }

Now URL admin.example.com/admin will redirect to show action of admin controller

Dynamic Constraint(Dynamic request matching)

  • Using matches? method

We can constraint route dynamically based on some specific criteria by creating a matches? method

Lets say we have to filter sub domain of URL

    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

What we are doing here is checking for URL if it start with sub domain foobar then only hit proxy#index action. Your class must have mathes? method either class method or instance method. If you want to make it a instance method then do

    constraints Subdomain.new do
      get '*path', to: 'proxy#index'
    end
  • Using lambdas

Instead of writing class we can also use lambdas ruby get '*path', to: 'proxy#index', constraints: lambda{|request|request.env['SERVER_NAME'].match('foo.bar')}

Resource