Whenever working with any kind of of CMS, human readable URL comes as a natural requirement. I used to use firendly_id for this. It's a solid gem for this purpose and featureful.

But most of the cases I don't need that much feature. Nowadays I take a simpler route. I use String#parameterize from Rails ActiveAupport with a before_validation callback. Something like below snippet:

before_validation :generate_slug, only: %i[create update]

private

def generate_slug
  self.slug = title.parameterize
end

But today I stumpled upon a case where the title can easily be duplicate, but I need unique slug. By default I reverted to candidates feature of friendly_id. I was feeling bit uneasy about installing a whole gem for just one model. It's not like I'm using it everywhere!

After about 10 minutes of thinking, I came up with a solution.

Here's how I did it:

before_validation :generate_slug, only: %i[create update]

private

def generate_slug
  self.slug = slug_candidates.each do |candidates|
    slug = candidates.map { |candidate| public_send(candidate) }.join(' ').parameterize
    break slug unless self.class.exists?(slug: slug)
  end
end

def slug_candidates
  [
    %i[name],
    %i[name city],
    %i[name street city],
  ]
end

I think it's fullfils my requirements, might also help you.




What's on your mind?