Friendly ID slug does not contain the id

和自甴很熟 提交于 2019-12-10 10:36:35

问题


I want to have urls like this:

http://domain.com/products/454-table-lamp

So I use friendly_id like so:

extend FriendlyId

friendly_id :slug_candidates, use: :history

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

Now, since friendly id generates the slug before the object is saved I end up with an url like so (Please note the missing id in the URL):

http://domain.com/products/table-lamp

Now while this is not too bad as such. As soon as I save another Product called "Table Lamp", I will get an URL like this:

http://domain.com/products/table-lamp-ebaf4bf5-a6fb-4824-9a07-bdda34f56973

So my question is, how can I make sure, friendly ID creates the slug containing the ID as well.


回答1:


Just add an after_commit callback to your model. In this callback, set slug to nil and save:

  after_commit :update_slug, on: :create

  def update_slug
    unless slug.include? self.id.to_s
      self.slug = nil
      self.save
    end
  end



回答2:


Well, the short answer - you can't. FrienlydId generates slug in before_validation callback here: https://git.io/vgn89. The problem is that you need to generate slug before saving to avoid conflicts, but you want to use information that available only after actual save, when record is already in db.

Take a look on this answer for details.

Of course, you can do something like if you really want it:

def slug_candidates
  [ title, Model.maximum(:id) + 1 ]
end

But this code is not thread safe and can lead to some obvious problems. Another way - change the slug after save, in after_create callback for example. You can set it to nil and call set_slug again.

But ask yourself - do you really need it? May be it is better to use timestamp from created_at for example as a part of slug candidates?



来源:https://stackoverflow.com/questions/35221139/friendly-id-slug-does-not-contain-the-id

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!