I have User and Campaign models. I nest campaigns under users and URLs look like this:
http://localhost:3000/user-slug/campaign-slug
Routes:
resources :users, :path => '' do
resources :campaigns, :path => ''
end
Campaign model:
class Campaign < ActiveRecord::Base
...
extend FriendlyId
friendly_id :title, use: :history
...
end
My User model doesn't use history.
Campaign controller (from friendly_id guide):
class CampaignsController < ApplicationController
before_filter :find_campaign
def show
@campaign = Campaign.friendly.find(params[:id])
end
private
def find_campaign
@campaign = Campaign.friendly.find(params[:id])
# If an old id or a numeric id was used to find the record, then
# the request path will not match the post_path, and we should do
# a 301 redirect that uses the current friendly id.
if request.path != campaign_path(@campaign)
return redirect_to @campaign, :status => :moved_permanently
end
end
end
When I visit an old slug to trigger redirection I get this error:
ActionController::UrlGenerationError in CampaignsController#show
No route matches {:action=>"show", :controller=>"campaigns", :format=>nil, :id=>nil, :user_id=>#<bunch of other stuff in here>} missing required keys: [:id]
Not sure how I should tweak the redirect method to make it work.
Managed to get it to work with this:
def find_campaign
@campaign = Campaign.friendly.find(params[:id])
@user = @campaign.user
# If an old id or a numeric id was used to find the record, then
# the request path will not match the campaign_path, and we should do
# a 301 redirect that uses the current friendly id.
request_slug = params[:id]
if request_slug != @campaign.slug
return redirect_to user_campaign_path(@user, @campaign), :status => :moved_permanently
end
end
Instead of comparing the request path I compared the request slug which doesn't have the part before the slash. And I needed to redirect to the correct route user_campaign_path
.