Custom routes in Rails

In the life of almost all Rails applications, comes the moment where custom routes are needed. Usually, the custom routes are just convenience methods like these:

def post_path(post)  
  date_post_path post.date_slug, post.slug
end

def product_url  
  date_post_url post.date_slug, post.slug
end  

In this way, you decouple the route generation from your objects. Also, if you are doing some system route update and you want to keep the old routes around - this is the way.

Usually, I create a module CustomPaths and put those methods there. But in recent years, Rails.application.routes.url_helpers is showing up in more and more places like - background jobs, presenters, serializers and so. This complicates things.

At Product Hunt we needed some custom paths. So, me and Mike Coutermarsh created the following object:

# => routes.rb
module Routes  
  # Simple `extend self` won't work here,
  # due to the way Rails implement `url_helpers`
  class << self
    include Rails.application.routes.url_helpers
    include Routes::CustomPaths
  end

  include Rails.application.routes.url_helpers
  include Routes::CustomPaths

  def default_url_options
    Rails.application.routes.default_url_options
  end
end

# => routes/custom_paths.rb
module Routes  
  module CustomPaths
    # ... all your custom route methods
  end
end  

It behaves the same way as Rails.application.routes.url_helpers plus the custom routes.

# in can be called directly
Routes.root_path  
Routes.product_path(product)

# or included in another object
class ObjectWhoNeedsRoutes  
  include Routes
end

ObjectWhoNeedsRoutes.new.root_path  
ObjectWhoNeedsRoutes.new.product_path  

I added Routes to my toolbox with install instructions and tests.