我目前在模型上使用acts_as_paranoid和friendly_id(5.0.1),当我销毁一个模型并尝试创建一个将生成相同 slug 的新模型时,我得到:
ERROR: duplicate key value violates unique constraint "index_papers_on_slug"
我需要以某种方式获取代码,以检查所有对象范围内是否已经存在 slug,而不仅仅是未删除的对象。
如何让friendly_id在检查 slug 是否已存在时使用with_deleted
。我应该指出,我也在使用鼻涕虫历史,这可能会使事情进一步复杂化。
深入挖掘后,我意识到由于我使用的是历史记录,因此 slug 被完全删除,而对象只是被软删除:
DELETE FROM "friendly_id_slugs" WHERE "friendly_id_slugs"."id" = $1 [["id", 9423]]
所以,我只需要弄清楚如何防止这种情况,我应该没问题,因为看起来friendly_id代码本身在尝试查找有效 slug 时已经在使用unscoped
。
将以下内容添加到模型中允许我覆盖对 slug 的依赖销毁
def has_many_dependent_for_slugs; end
解决方案来自对此github问题的评论。
Friendly_id有一个名为scoped
的模块,它允许你在作用域内生成唯一的 slug。所以,可能
class Paper < ActiveRecord::Base
extend FriendlyId
friendly_id :title, :use => :scoped, :scope => :unscoped
end
将解决问题。
我也遇到了这个问题,我想到了两种不同的方法来解决这个问题。
解决方案 1:
使用dependent: false
.
friendly_id :title, dependent: false
解决方案:2
克服这个问题,而不会覆盖任何想要避免这种情况的人的依赖destroy
。
friendly_id gem 使用名为 scope_for_slug_generator
的方法来设置模型范围。这意味着我们可以通过将以下内容添加到 app/config/initializers/friendly_id.rb
来覆盖此方法。
module FriendlyId
def scope_for_slug_generator
scope = if self.class.base_class.include?(Paranoia)
self.class.base_class.unscoped.with_deleted
else
self.class.base_class.unscoped
end
scope = self.class.base_class.unscoped
scope = scope.friendly unless scope.respond_to?(:exists_by_friendly_id?)
primary_key_name = self.class.primary_key
scope.where(self.class.base_class.arel_table[primary_key_name].not_eq(send(primary_key_name)))
end
end