Is is possible to force a 301 redirect when someone attempts to browse to a page using the old /:id
URL, rather than than the preferred /:friendly_id
link?
Apparently such redirections help to tell Google that you have updated the link.. so it stops displaying the old non-friendly link.
While James Chevalier's answer is correct, you can extract this method to the ApplicationController in order to use with any model that uses FriendlyId:
def redirect_resource_if_not_latest_friendly_id(resource)
# This informs search engines with a 301 Moved Permanently status code that
# the show should now be accessed at the new slug. Otherwise FriendlyId
# would make the show accessible at all previous slugs.
if resource.friendly_id != params[:id]
redirect_to resource, status: 301
end
end
As you can see it's also unnecessary to pass a specific action
key to redirect_to
. Passing a Rails model to redirect_to
will automatically attempt to access the show
action on the associated collection resource route (assuming it's set up that way). That also means it's unnecessary to pass an id
key since FriendlyId always returns the latest slug in the model's #to_param
.
Not being a huge fan of unless
(confusing semantics) I tend to shy away from it but that's more my personal preference.
With the latest version of friendly_id (5.0.3 at the time of writing this answer) and Rails 4, I do this in the controller:
class ItemsController < ApplicationController
before_action :set_item, only: [:show, :edit, :update, :destroy]
...
private
def set_item
@item = Item.friendly.find(params[:id])
redirect_to action: action_name, id: @item.friendly_id, status: 301 unless @item.friendly_id == params[:id]
end
end
Here's a description of the redirect_to
line, broken down piece by piece:
action: action_name
retains the action that you're connecting to (which can be show, edit, update, or destroy based on the before_action
that's in place) so that if you're accessing /items/1/edit
you will be redirected to /items/pretty-url/edit
id: @item.friendly_id
ensures that the URL you're being redirected to is the pretty URLstatus: 301
sets the redirect to the status of 301, for SEOunless @item.friendly_id == params[:id]
makes sure that we're not redirecting people who access @item
through its pretty URLIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With