5
votes

I have the following in my model:

class Dispenser < ActiveRecord::Base

  extend FriendlyId

  friendly_id :slug_candidates, use: :slugged

  def slug_candidates
    [
      :full_name,
      [:full_name, :id]
    ]
  end

end

This is generating slugs like:

=> 'bob-barker-bob-barker-15'

Really it should be bob-barker or bob-barker-15, but not both.

https://github.com/norman/friendly_id

4
Not that it is the source of the issue, but you shouldn't have a comma after the last element in your slug_candidates array [:full_name, :id], <<<Damien Roche
what version of friendly_id are you using? did you try using the github master? I think you should always use symbols, otherwise all the fields will get evaluated when the method is called.phoet
Ok, fixed symbols and comma and using friendly_id (4.0.10.1) ... still no gloryAbram
so it looks like the functionality you're looking for is only available in version 5 github.com/norman/friendly_id#what-changed-in-version-50Matenia Rossides

4 Answers

9
votes

FriendlyId author here. As mentioned earlier, you need FriendlyId 5 for this, it won't work with 4.0.

Also note that you can not use the id field as a part of the slug, because the slug is generated before the record is created.

If you are willing to have the id field in the slug, then there are easier solutions available other than FriendlyId, such as overriding the to_param method as described here.

4
votes

[:full_name, :id] - you can do this only onUpdate (when :id already set) When you are creating a new record in your DB table this will not work!

For you purpose you should use some like this

def slug_candidates
[
  :name,
  [:name, 2],
  [:name, 3],
  [:name, 4],
  [:name, 5],
  [:name, 6],
  [:name, 7],
]

end

Or shortly

def slug_candidates
  [:name] + Array.new(6) {|index| [:name, index+2]}
end

It's simple way to solve this problem without extra SQL query

3
votes

The functionality you're describing is in version 5

See: https://github.com/norman/friendly_id#what-changed-in-version-50

What you've written is essentially just returning an array of symbols which is running through the parameterize method after it's cast to a string ...

2.0.0p247 :002 > ['name',['name',15]].to_s.parameterize # this is what friendly_id does in the background
 => "name-name-15"

Hope that helps

3
votes

On slug conflicts, FriendlyID by default uses the UUID (e.g. something like 2bc08962-b3dd-4f29-b2e6-244710c86106) and won't accept id. So something like this won't work:

def slug_candidates
  [
    :full_name,
    [:full_name, :id]
  ]
end

But you can provide a custom number after the :full_name instead of :id.

I did something like this:

def slug_candidates
  [
    :full_name,
    [:full_name, "#{User.where(
        first_name: first_name, last_name: last_name
      ).count + 1}"]
  ]
end

So I will get slugs like john-doe, john-doe-2, john-doe-3, etc.