in Railscasts, Uncategorized

Railscast 046 Catch All Route

The GitHub Repo
The Heroku App

This episode focused on creating a catch all route that redirects to a product’s page based on the partial route typed in. Example: /tele to /television

The routes syntax has been updated since the creation of the episode.

match '*path' => 'your_controller#your_action', via: :get

StackOverflow

You would want to create this catch all route at the bottom of your routes file because it would match all the requests coming into you Rails app otherwise. Because the match all routes redirects to the product page you actually are looking for, this isn’t that bad of an outcome.

After the route catches the input of the user from the route, it then calls the redirect#index. In this controller we can control the behavior of that route.

class RedirectController < ApplicationController
  def index
    if Rails.env.development? || Rails.env.test?
      product = Product.where('name LIKE ?', "#{params[:path].first}%").first
    elsif Rails.env.production?
      product = Product.where('name ILIKE ?', "#{params[:path].first}%").first
    end
    redirect_to product_path(product)
  end
end

In this controller I reused what I learned about PostgreSQL’s LIKE and ILIKE functions from the episode about Simple search forms to separate difference lines of code based on the environment.

There is a single action, index, that is called from the catch all route. We find where the product has a name that is similar to the partial parameter given in the route. We access this partial parameter through the params has with params[:path]. We also call first() to get the first value of the hash. If the user inputed /foo/bar/baz, then it would use the foo value only. Again from episode 037 simple search form, we use the SQL Wildcard % to match anything that starts with the partial route given. If there are multiple records that have the same partial route, then we call first() again at the end of the line to only retrieve the first record.

get '*path' => 'redirect#index'