Use Numeric Sequence for Duplicate Slugs [Friendly

2019-09-20 01:48发布

问题:

I noticed on the docs it says: Previous versions of FriendlyId appended a numeric sequence to make slugs unique, but this was removed to simplify using FriendlyId in concurrent code.

Is there any way to revert back to this format? My model only has name so there aren't any other viable slug candidates and (time or date wouldn't make sense in this case for slug candidates).

How can I change this (current format):

car.friendly_id #=> "peugeot-206"
car2.friendly_id #=> "peugeot-206-f9f3789a-daec-4156-af1d-fab81aa16ee5"
car3.friendly_id #=> "peugeot-206-f9dsafad-eamj-2091-a3de-fabsafafdsa5"

Into this:

car.friendly_id #=> "peugeot-206"
car2.friendly_id #=> "peugeot-206-1"
car3.friendly_id #=> "peugeot-206-2"

回答1:

Old behaviour was implemented in special module. But at the moment it has not been released yet. So, if you want to restore old behaviour you can switch friebdly_id in your Gemfile on Github and add sequentially_slugged to the modules list.



回答2:

I realize you said

(time or date wouldn't make sense in this case for slug candidates)

But in assuming you we're only referring to the string format of time and not unix which is a numeric sequence then I came up with this workaround to your problems/concerns:

  1. your model only has name attribute
  2. you can't use id to append to the slug because it hasn't been created yet
  3. you want the slugs to be uniq and incrementing
  4. you don't want to use UUID

# app/models/car.rb
class Car < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, use: :slugged

  def normalize_friendly_id(string)
    incremented_number = (Time.now.to_f * 1000000).to_i
    "#{super}-#{incremented_number}"
  end
end

So now this works

car1 = Car.create(name: "peugeot")
car2 = Car.create(name: "peugeot")
car3 = Car.create(name: "peugeot")

car1.friendly_id #=> "peugeot-1451368076324115"
car2.friendly_id #=> "peugeot-1451368076457560"
car3.friendly_id #=> "peugeot-1451368076460087"

Note: the numbers are incrementing

Time.now.to_f * 1000 would be miliseconds and I'm using Time.now.to_f * 1000000 which is MICROSECONDS <- that's one millionth of a second. It's NOT going to be created at the same time and therefore won't run into slug conflicts. And if someone out there thinks it could then just add a few more zeros to that multiplier.



回答3:

There are good reasons that "serial number" was replaced by UUID (race conditions).
I normally use an additional slug candidate with the ID, that is maintained uniq by the db and much shorter than an UUID:

[ [:name], [:name, :id] ]