Search code examples
ruby-on-railsfriendly-id

Old urls are still working after implementing friendly_id on rails app. How can I stop them and redirect to 404?


I implemented friendly_id on my rails app. Earlier when clicked on a link the url used to look like below:

https://example.com/search?category_id=228

After implementing friendly_id when the link was clicked it started to give url as follows:

https://example.com/search?category_id=construction-and-heavy-equipment 

I have a 404 method implemented on the platform. When given invalid urls it redirects to 404 error page. It works fine for invalid urls.

But now when I tested giving the old url i.e https://example.com/search?category_id=228 it is still working. How can I stop this?

controller

  def search_equipments
    begin
      if (params.keys & ['category_id', 'sub_category', 'manufacturer', 'country', 'state', 'keyword']).present?
        if params[:category_id].present?
          @category = Category.active.find params[:category_id]
        else
          @category = Category.active.find params[:sub_category] if params[:sub_category].present?
        end
        @root_categories = Category.active.roots
        @sub_categories = @category.children.active if params[:category_id].present?
        @sub_categories ||= {}
        @countries = Country.active.all
        @manufacturers = Manufacturer.active.all
        @states = State.active.where("country_id = ?", params[:country]) if params[:country].present?
        @states ||= {} 
        unless params[:category_id].present? && params[:sub_category].present?
          params[:category_id] = @category.id if params[:category_id].present?
          params[:sub_category] = @category.id if params[:sub_category].present?
        end   
        @equipments = Equipment.active.filter(params.slice(:manufacturer, :country, :state, :category_id, :sub_category, :keyword)).order("#{sort_column} #{sort_direction}, created_at desc").page(params[:page]).per(per_page_items)               
      else
        redirect_to root_path
      end
    rescue Exception => e
      redirect_to root_path, :notice => "Something went wrong!"
    end

  end

concerns

module Filterable
  extend ActiveSupport::Concern

  module ClassMethods
    def filter(filtering_params)
      results = self.where(nil)
      filtering_params.each do |key, value|
        results = results.public_send(key, value) if value.present?
      end
      results
    end
  end
end

Solution

  • According to the friendly_id source code, you should use find_by_friendly_id. Because the find method first query by slug, then fall back to the regular find method.

    # If the id is "unfriendly", it will call the original find method.
    # If the id is a numeric string like '123' it will first look for a friendly
    # id matching '123' and then fall back to looking for a record with the
    # numeric id '123'.
    #
    # Since FriendlyId 5.0, if the id is a numeric string like '123-foo' it
    # will *only* search by friendly id and not fall back to the regular find
    # method.
    #
    # If you want to search only by the friendly id, use {#find_by_friendly_id}.
    

    Change code

    @category = Category.active.find params[:category_id]
    

    to this

    @category = Category.active.friendly.find_by_friendly_id params[:category_id]
    

    And check https://github.com/norman/friendly_id/issues/648#issuecomment-75172624, it's another solution, but more complex.