Friendly_id 为 Rails 中的多个对象创建重复的 slug
Friendly_id creating duplicate slugs for multiple objects in Rails
我的 Rails 构建不包含路径名。该应用程序由两个主要对象组成:collections
和 items
。因此,如果我有一个 link: https://foo.com/foo,这可能会标识一个集合或一个项目。上下文中的区别很明显,并且 UI 在整个应用程序中流动。
我的问题:有没有办法让 Friendly ID gem 通过查看一个 slug 是否已经被另一个对象带走来生成唯一的 slug?我知道您可以生成候选者,以便友好 ID 不会为给定对象复制一个 slug,但我需要友好 ID 来检查现有的集合 slug 和项目 slug,然后再生成一个新的 slug。
我希望这听起来不会太混乱。更简洁地重新表述:是否有一种方法可用于友好 ID 在生成新 slug 之前检查多个对象中的 slug?
注意这一切都未经测试,只是从文档中工作并阅读源代码。
您可以继承 FriendlyId::SlugGenerator class,并覆盖 available? 方法来检查现有的对手模型中的记录:
class CrossModelSlugGenerator << FriendlyId::SlugGenerator
def available?(slug)
if (@scope.class == "Item::ActiveRecord_Relation")
# Search for collections with this slug and return false if they exist.
elsif (@scope.class == "Collection::ActiveRecord_Relation")
# Search for items with the this slug and return false if they exist.
end
# Otherwise do a normal slug check
!@scope.exists_by_friendly_id?(slug)
end
end
您可以在此处查看 SlugGenerator class 的完整代码:
https://github.com/norman/friendly_id/blob/master/lib/friendly_id/slug_generator.rb
然后您必须告诉友好 ID 配置使用那个 class。在 config/intitializers/friendly_id.rb:
中创建初始化器
FriendlyId.defaults do |config|
config.slug_generator_class = "CrossModelSlugGenerator"
end
尝试一下,看看是否适合您。同样,我还没有测试过任何一个,但它似乎应该可行。
编辑 - 您可能需要像这样在 FriendlyId 模块中包装 class:
您可能需要在某处包含,可能在您的 class 定义中。另外,尝试将 class 包装到 FriendlyId 模块中,所以可能是这样的:
include "friendly_id"
module FriendlyId
class CrossModelSlugGenerator << SlugGenerator
...
end
end
进行此更改后,您可能还需要在配置中明确指定模块 class 名称:
FriendlyId.defaults do |config|
config.slug_generator_class = "FriendlyId::CrossModelSlugGenerator"
end
我的 Rails 构建不包含路径名。该应用程序由两个主要对象组成:collections
和 items
。因此,如果我有一个 link: https://foo.com/foo,这可能会标识一个集合或一个项目。上下文中的区别很明显,并且 UI 在整个应用程序中流动。
我的问题:有没有办法让 Friendly ID gem 通过查看一个 slug 是否已经被另一个对象带走来生成唯一的 slug?我知道您可以生成候选者,以便友好 ID 不会为给定对象复制一个 slug,但我需要友好 ID 来检查现有的集合 slug 和项目 slug,然后再生成一个新的 slug。
我希望这听起来不会太混乱。更简洁地重新表述:是否有一种方法可用于友好 ID 在生成新 slug 之前检查多个对象中的 slug?
注意这一切都未经测试,只是从文档中工作并阅读源代码。
您可以继承 FriendlyId::SlugGenerator class,并覆盖 available? 方法来检查现有的对手模型中的记录:
class CrossModelSlugGenerator << FriendlyId::SlugGenerator
def available?(slug)
if (@scope.class == "Item::ActiveRecord_Relation")
# Search for collections with this slug and return false if they exist.
elsif (@scope.class == "Collection::ActiveRecord_Relation")
# Search for items with the this slug and return false if they exist.
end
# Otherwise do a normal slug check
!@scope.exists_by_friendly_id?(slug)
end
end
您可以在此处查看 SlugGenerator class 的完整代码:
https://github.com/norman/friendly_id/blob/master/lib/friendly_id/slug_generator.rb
然后您必须告诉友好 ID 配置使用那个 class。在 config/intitializers/friendly_id.rb:
中创建初始化器FriendlyId.defaults do |config|
config.slug_generator_class = "CrossModelSlugGenerator"
end
尝试一下,看看是否适合您。同样,我还没有测试过任何一个,但它似乎应该可行。
编辑 - 您可能需要像这样在 FriendlyId 模块中包装 class:
您可能需要在某处包含,可能在您的 class 定义中。另外,尝试将 class 包装到 FriendlyId 模块中,所以可能是这样的:
include "friendly_id"
module FriendlyId
class CrossModelSlugGenerator << SlugGenerator
...
end
end
进行此更改后,您可能还需要在配置中明确指定模块 class 名称:
FriendlyId.defaults do |config|
config.slug_generator_class = "FriendlyId::CrossModelSlugGenerator"
end