友情ID slug不包含id

时间:2016-02-05 09:58:40

标签: ruby-on-rails friendly-id

我想要这样的网址:

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

所以我像这样使用friendly_id:

extend FriendlyId

friendly_id :slug_candidates, use: :history

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

现在,由于友好ID在保存对象之前生成了slug,我最终会得到一个类似的URL(请注意URL中缺少的id):

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

现在虽然这并不是那么糟糕。一旦我保存另一个名为" Table Lamp"的产品,我将得到一个这样的URL:

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

所以我的问题是,我怎样才能确定,友好的ID也会创建包含ID的slug。

2 个答案:

答案 0 :(得分:7)

只需在模型中添加after_commit回调即可。在此回调中,将slug设置为nil并保存:

  after_commit :update_slug, on: :create

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

答案 1 :(得分:2)

嗯,简短的回答 - 你不能。 FrienlydId在def slug_candidates [ title, Model.maximum(:id) + 1 ] end 回调中生成slu :: https://git.io/vgn89。问题是你需要在保存之前生成slug以避免冲突,但是你想要使用仅在实际保存之后可用的信息,当记录已经在db中时。

看一下answer for details

当然,你可以做一些事情,如果你真的想要它:

after_create

但是这段代码不是线程安全的,可能导致一些明显的问题。另一种方法 - 例如在nil回调中更改保存后的slug。您可以将其设置为set_slug并再次致电meta(property='og:url', content='#{pageUrl} == '' ? 'a' : 'c'')

但问问自己 - 你真的需要它吗?也许最好使用created_at中的时间戳,例如作为slug候选者的一部分?