Friendly_id gem using UUIDs despite being overrriden - ruby-on-rails

I have a model, and in accordance with the friendly_id gem it looks like this:
class FinancialYear < ApplicationRecord
extend FriendlyId
friendly_id :slug_candidates, use: :slugged
def slug_candidates
[
:end_year,
[:end_year, :max_id]
]
end
def should_generate_new_friendly_id?
self.slug.blank? || self.year_changed?
end
def end_year
if !self.year.nil? && self.year.length > 1
self.year.split('-')[-1].strip
else
self.year
end
end
def max_id
FinancialYear.where(year: end_year).count + 1
end
end
What it's supposed to do is turn a year:'1999-2000' into a slug: '2000' and 2000-2...etc to avoid collisions.
Unfortunately my tests are failing expected: "2000", got: "2000-f7608e8b-a2e7-449c-ae54-4785c7a68dec"
I am using friendly_id on another model in my app and am using the same technique, and its working perfectly. Any help or suggestions as to why this isn't working would be very appreciated.
UPDATE
After more experimentation I've discovered that this seems to only be happening in my rspec tests - but I don't understand why? Any thoughts?

i had the same issue,i resolved it by deleting all slug values first and then re-running my save.
###delete all slug values
User.update_all(:slug=>nil)
###re-run to get the new slug candidate affective overriding the default alpanumeric slug
User.find_each(&:save)
Hope it helps.

Related

Use the ID inside slug when using FriendlyID

Inside my model, I have the following:
friendly_id :id_and_title, use: [:slugged, :finders]
...
def id_and_title
"#{self.id}-#{self.title}"[0,100]
end
However, when creating a new record, the ID isn't being used on the slug field.
What I'm currently doing is:
after_save :regenerate_slug
...
def regenerate_slug
self.slug = nil
self.save
end
and I'm wondering if there is any other way of doing this?
So the problem is that friendly_id does not have access to "id" until after the record is created. The issue here is the after_save causes infinite recurrence, like Michal said, since it calls save.
You should use an after_create instead. You only need to do this once. In all subsequent updates to the record the id should be available for friendly_id to pick up.
#user3062913 has the solution for it here:
Rails4 Friendly_id Unique Slug Formatting

Rails 4 Friendly Id Slug Not Updating

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
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
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.
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)

Slug Based on two values

First off I'm very new to rails and ruby for that matter.
I'm trying to create a slug for custom URLS.
I have a user model with a first_name & last_name. This model also has a slug.
What I am trying to do is get it to check my database to see if there is an instance of the slug to be created eg. see how many Joe Blogs exist. If there is none it gets the url whatever.com/joe-blogs and if there more than 0 it gets the value of the count whatever.com/joe-blogs-COUNT
what I attempted to do when gerating my slug
def generate_slug
NoSlug == Users.sum("slug").where(:slug => first_name-last_name.perameterize)
if NoSlug == 0
self.slug ||= first_name-last_name.perameterize
else NoSlug > 0
self.slug ||= first_name-last_name-NoSlug.perameterize
end
end
I've tried to fix it but with no such luck - Any suggestions or pointers?
Thanks!
I have been using the FriendlyId gem and have been pleased. If you want to combine first name and last name, you could do something like
class User < ActiveRecord::Base
extend FriendlyId
friendly_id :full_name, use: :slugged
def full_name
"#{first_name} #{last_name}"
end
end
The gem will take care of parameterizing it for you. This RailsCast might also be helpful.
write these methods in model
before_validation :generate_slug
def name
"#{first_name} #{last_name}"
end
def generate_slug
self.slug = self.name.downcase.gsub(/\s+/, '-').gsub(/[^a-zA-Z0-9_]+/, '')
end

Friendly_id not creating slugs for old records

I just added the Friendly_id gem to my rails project looking to not use the database id and create a slug, but I can't seem to create slugs for old records. My model looks like this.
class Mapping < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
# Friendly_Id code to only update the url for new records
def should_generate_new_friendly_id?
new_record? || slug.blank?
end
end
I then am running Model.find_each(&:save) but it keeps spitting out a nil result. I've tried commenting out the should_generate_new_friendly_id completely but with no luck. Anyone see what I'm doing wrong here?
EDIT
I rolled my database back and rewrote my migratations and that has appeared to have fixed the issue.
If anyone finds this 6 year old question:
Without a "do and end" block:
find_each returns an Enumerable (not an ActiveRecord Class)
Use:
Model.find_each.select(&:save)
Notice the added "select" method
Doing stuff with Rails’ find_each

Rails FriendlyId and normalize_friendly_id

Trying to get my app running the FriendlyId gem (version 4.0.1)
I think I'm doing this in the wrong order, but I want to strip out apostrophes before my friendly_id slug is generated when creating a new record. But I think the method normalize_friend_id is being called after the id is already generated.
I've added the following to my model:
class Team < ActiveRecord::Base
extend FriendlyId
friendly_id :name, :use => :slugged
def normalize_friendly_id(string)
super.gsub("\'", "")
end
end
super calls the superclass first, meaning the friendly id is being generated then you're running gsub on THAT result. What you really want is to override this method completely.
Refer to: https://github.com/norman/friendly_id/blob/master/lib/friendly_id/slugged.rb#L244-246
your code should look like this:
def normalize_friendly_id(string)
string.to_s.gsub("\'", "").parameterize
end
or
def normalize_friendly_id(string)
super(string.to_s.gsub("\'", ""))
end
Hope that helps

Resources