Rails: Friendly_id does not generate slugs for old records
-
27-06-2021 - |
Question
I've used the FriendlyId gem (version 4.0.8) with a Rails application. I've followed the tutorial on RailsCasts and based on the documentation, I have to run Model.find_each(&:save)
on rails console to generate slugs for old records. However, when I do this, all of my old records still have nil for their slug attributes, so it doesn't really change the url's.
Am I doing something wrong? This only happens on production by the way. It works fine on development.
Update:
My model looks like this:
class Member < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
belongs_to :gym
attr_accessible :category, :name, :description
validates :category, :name, :description, :presence => true
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }
def self.search(search)
if search.present?
where("name LIKE ?", "%#{search}%")
else
find(:all)
end
end
def should_generate_new_friendly_id?
new_record?
end
end
Solution
should_generate_new_friendly_id?
is returning false since new_record?
is false, since your records already exist.
Delete the should_generate_new_friendly_id?
method, or try this & re-run:
def should_generate_new_friendly_id?
new_record? || slug.blank?
end
See also: Rails Friendly_Id on Heroku, Heroku not updating slugs
OTHER TIPS
I had this same challenge when working on a Rails 6 application.
Here's how I solved it:
By default Friendly_id gem does not generate slugs for existing records in a Rails application. So if you have existing records for a model, slugs won't be generated for them. They will only be generated for newer records.
To generate slugs for existing records, do the following. Say our model name is Blog
and the column we want to use for the slug is title
, we will do the following:
Be sure to first add a slug column to the
Blog
table:rails g migration AddSlugToBlogs slug:uniq
Next, generate the friendly configuration file and a new migration (if you've not already done it):
rails generate friendly_id
Next, run your database migration:
rails db:migrate
Next, edit the
app/models/blog.rb
file as the following:class Blog < ApplicationRecord extend FriendlyId friendly_id :title, use: :slugged end
Next, edit the
app/controllers/blogs_controller.rb
file and replace Blog.find by Blog.friendly.findclass BlogController < ApplicationController def show @blog = Blog.friendly.find(params[:id]) end end
OR
class BlogsController < ApplicationController before_action :set_blog, only: %i[ show edit update destroy ] def show end private # Use callbacks to share common setup or constraints between actions. def set_blog @blog = Blog.friendly.find(params[:id]) end end
Finally, start your rails console and run the command below to generate slugs for existing records:
rails console Blog.find_each(&:save)
Note: You will have to run this command in all environments where you have existing records, say, test, staging, and production, to generate slugs for the records in those environments as well.
Now, when you create a new blog like the following with say title - My first blog, you will be able to access the blog show page using the URL http://localhost:3000/blogs/my-first-blog.
That's all.
I hope this helps