1

I've been following the Railscast tutorial on how to implement friendly_id and for some reason my URL's doesn't change after I update my attributes.

Say I registered a user with :fullname 'John Doe' it creates the slug /john-doe successfully. However if I update my name to 'Test user' the url is still /john-doe

My current setup is this:

users_controller

def show
 @user = User.friendly.find(params[:id])
end

model - user.rb

extend FriendlyId
 friendly_id :fullname, use: [:slugged, :history]

I've also migrated

class AddSlugsToUsers < ActiveRecord::Migration
 def change
  add_column :users, :slug, :string
  add_index :users, :slug, unique: true
 end
end

so that is working. Also installed

rails generate friendly_id

and done:

User.find_each(&:save)

in rails c

What am I doing wrong?

user2755537
  • 151
  • 1
  • 9

1 Answers1

4

friendly_id

It's a common issue with friendly_id - it defaults to setting the slug only if the slug attribute is blank:


Documentation

As of FriendlyId 5.0, slugs are only generated when the slug field is nil. If you want a slug to be regenerated,set the slug field to nil:

restaurant.friendly_id # joes-diner
restaurant.name = "The Plaza Diner"
restaurant.save!
restaurant.friendly_id # joes-diner
restaurant.slug = nil
restaurant.save!
restaurant.friendly_id # the-plaza-diner

You can also override the #should_generate_new_friendly_id? method, which lets you control exactly when new friendly ids are set:

class Post < ActiveRecord::Base
  extend FriendlyId
  friendly_id :title, :use => :slugged

  def should_generate_new_friendly_id?
    title_changed?
  end
end

If you want to extend the default behavior but, adding your own conditions, don't forget to invoke super from your implementation:

class Category < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, :use => :slugged

  def should_generate_new_friendly_id?
    name_changed? || super
  end
end

For you, I'd recommend:

#app/models/user.rb
Class User < ActiveRecord::Base
   ...

   def should_generate_new_friendly_id?
      name_changed? || super
   end
end
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • 1
    that worked. However I want to do a 301 redirect on old urls and I tried adding def show @user = User.friendly.find(params[:id]) if request.path != user_path(@user) redirect_to @user, status: :moved_permanently end end but got undefined method `user_path'. The show file (profile page) is stored inside 'users/show.html.erb' so why isn't that path working? My routes are setup like this: get '/intern/:id', to: 'users#show' – user2755537 Jun 28 '14 at 11:59
  • You'll need to include the [`history`](http://rubydoc.info/github/norman/friendly_id/master/FriendlyId/History) option in `friendly_id` - this will create a table called `friendly_id_slugs`, which will store historic data (which will redirect automatically) – Richard Peck Jun 28 '14 at 12:02
  • I did: friendly_id :slug_candidates, use: [:slugged, :history] # Try building a slug based on the following fields in # increasing order of specificity. def slug_candidates [ :fullname, [:fullname, :id] ] end and I have generated the friendly_id table but I want it to redirect the URL so if I go to /rich-1 and change it to rich-2 and visit rich-2 it needs to redirect you to rich-2. If that makes sense? – user2755537 Jun 28 '14 at 12:08
  • Did you try restarting your Rails server/ – Richard Peck Jun 28 '14 at 12:29
  • Figured out the problem. It was my routing. – user2755537 Jun 28 '14 at 12:35
  • Hell yes :) now I can visit rich-1 and it redirects me to rich-2 (the current url) and everything else working fine as-well. Due to your def .... name_changed? || super end Only problem now is my slug_candidates. Trying to add :fullname, Random.new.rand(1..100) so I avoid the ugly UUID . However not working. – user2755537 Jun 28 '14 at 12:45
  • It's another feature of `friendly_id` I think - there is a way to change it, but I can't remember unfortunately ^_^. Glad it helped though! – Richard Peck Jun 28 '14 at 12:49
  • 1
    got it working now with: friendly_id :slug_candidates, use: [:slugged, :history] def slug_candidates [ :fullname, [:fullname, Random.new.rand(1..100)] ] end – user2755537 Jun 28 '14 at 12:51