Reputation: 6071
I'm using the following:
gem 'friendly_id', github: 'FriendlyId/friendly_id', branch: 'master'
I am creating an Article section on my Rails 4 website. The problem I am having is that when I change a existing article's name the slug is not updated.
This is what I have so far:
extend FriendlyId
friendly_id :name, use: :slugged
add_column :articles, :slug, :string
add_index :articles, :slug, unique: true
Upvotes: 26
Views: 13212
Reputation: 8422
I was facing a similar issue where the slug don't want to change on update even though I had the following in my model:
def should_generate_new_friendly_id?
slug.blank? || title_changed?
end
In my case I wasn't setting the title directly via the form but in a before_save
callback, and that was the reason, because it seems that FriendlyID needs the change to happen not only before saving but even before_validation
so I changed my code to:
before_validation :set_title
def set_title
self.title = 'some dynamic way of getting title'
end
And, that worked for me!
I really spent too much time trying to figure out why it wasn't working, so I'm posting this case here for anyone who may get stuck in the same situation (and hopefully save you long hours of debugging)
Upvotes: 2
Reputation: 10592
In FriendlyId 4 (Rails 3 compatible) there was a method
should_generate_new_friendly_id?
and you could define it on your model to control when slug is regenerated. Try
def should_generate_new_friendly_id?
name_changed?
end
to regenerate slug when name changes.
EDIT
FriendlyId version 5 (Rails 4 compatible) doesn't regenerate slugs on save anymore. To restore this functionality you can either set slug column to nil
before saving or use the solution provided above.
EDIT 2
You need to override the slug setter for your saves to work for Rails <5 & FriendlyId > 5 as referenced in this issue.
Add this to the model file
def slug=(value)
if value.present?
write_attribute(:slug, value)
end
end
Upvotes: 61
Reputation: 1043
I have this issues and just want to point out what I've noticed.
if you only do as in docs
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
end
and then run Post.find_each(&:save)
- slug is gonna get updated...
However in my case, I also have these in my model
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
def normalize_friendly_id(text)
text.to_slug.normalize(transliterations: :russian).to_s
end
def should_generate_new_friendly_id?
title_changed?
end
end
with the code above it won't do anything when you run Post.find_each(&:save)
I assume since your title doesn't change. (first method handles russian language)
so when working with the first model all worked great, but then when I copied ready code to next model I wanted to slugify, I run into some issues. Hope it helps someone.
Upvotes: 6