1

I'm building a Rails app that has a merchant subdomain. I have these two routes:

get '/about', controller: :marketing, action: :about, as: :about
get '/about', controller: :merchant, action: :about, constraints: { subdomain: 'merchant' }, as: :merchant_about

But when I use their URL helpers both merchant_about_url and about_url result in http://example.com/about.

I know I can specify the subdomain argument on the helper to prefix the URL with the subdomain, but since these URLs are going to be frequently used in various cases I'd like to build a wrapper for this helper to make it smarter.

My question: Can I inspect a given route to see if it has a subdomain constraint?

If I can, I'd like to do something like the following:

def smart_url(route_name, opts={})
  if # route_name has subdomain constraint
    opts.merge!({ subdomain: 'merchant' })
  end

  send("#{route_name}_url", opts)
end

In doing this, I can effectively call:

smart_url('about')          # http://example.com/about
smart_url('merchant_about') # http://merchant.example.com/about

Is this possible?

Jody Heavener
  • 2,704
  • 5
  • 41
  • 70

2 Answers2

0

Can I inspect a given route to see if it has a subdomain constraint?

Yes, that is possible. You need to use Rails' routes API to get info about the route.

def smart_url(route_name, opts={})
  route = Rails.application.routes.routes.detect {|r| r.name == route_name }

  if opts.is_a? Hash && route&.constraints[:subdomain]
    opts.merge!({ subdomain: 'merchant' })
  end

  send("#{route_name}_url", opts)
end

The above searches a route by its name, and inspects its constraints if the route is found.

31piy
  • 23,323
  • 6
  • 47
  • 67
  • This is perfect! Thank you so much :) If you have a minute, I'm running in to one issue where `opts` can be an AR model instead of a hash. For example, `user_url(@user)` (`smart_url('user', @user)`). I can't append the `subdomain` argument to this. Any thoughts? – Jody Heavener Jun 21 '17 at 15:51
  • 1
    @JodyHeavener -- Please check my updated answer. You can manually typecheck for such situations. – 31piy Jun 21 '17 at 16:53
-1

you can create class under lib folder like this

class Subdomain
    def self.matches?(request)
        case request.subdomain
        when SUB_DOMAIN_NAME
          true
        else
          false
        end
    end
end

and in your routes.rb file create routes like this

constraints(Subdomain) do
    get '/about', to: 'marketings#about', as: :about
end

get '/about', to: 'marketings#about', as: :merchant_about