【问题标题】:Make friendly_id scope play nice with subclassed ActiveRecord model使用子类 ActiveRecord 模型使friendly_id 范围发挥得很好
【发布时间】:2014-02-06 19:12:03
【问题描述】:

我有一个子类 ActiveRecord 模型,它使用单独的表来存储记录,并使用 friendly_id (4.1.0.beta.1) 来生成 slug。问题是friendly_id 使用父类的表来检查现有的slug,而不是使用子表。基本上我希望friendly_id 将其检查范围限定在正确的表中。

例子:

class Parent
  friendly_id :name, :use => :slugged
end

class Child < Parent
  self.table_name = 'children'
end

Parent.create(name: 'hello').slug
> 'hello'

Child.create(name: 'hello').slug
> 'hello--2'

我希望friendly_id 为第二次创建生成'hello' slug,因为children 表中没有包含该slug 的记录。有没有办法配置或修补类友好 id 用于其查询的方法?

编辑:添加 friendly_id 版本以供将来参考

【问题讨论】:

    标签: ruby activerecord friendly-id


    【解决方案1】:

    我正在发布我自己的解决方案,以防万一有人遇到同样的问题。我应该重申,这个问题是在friendly_id gem 的4.1.0.beta.1 版本(当时是最新版本)上发现的,所以这个问题可能不会再发生了。

    为了解决这个问题,我基本上将slug_generator_class配置为使用我自己的类,这样我就可以猴子修补罪魁祸首方法。

    在我的模型中:

    friendly_id do |config|
      config.slug_generator_class = SubclassScopableSlugGenerator
    end
    

    在初始化程序中,我覆盖了 FriendlyId::SlugGenerator.conflicts 方法,因此我可以访问 sluggable_class 变量:

    # Lets a non-STI subclass of a FriendlyId parent (i.e. a subclass with its
    # own dedicated table) have independent slug uniqueness.
    class SubclassScopableSlugGenerator < FriendlyId::SlugGenerator
      private
      def conflicts
        # this is the only line we're actually changing
        sluggable_class = friendly_id_config.model_class
    
        pkey  = sluggable_class.primary_key
        value = sluggable.send pkey
        base = "#{column} = ? OR #{column} LIKE ?"
        # Awful hack for SQLite3, which does not pick up '\' as the escape character without this.
        base << "ESCAPE '\\'" if sluggable.connection.adapter_name =~ /sqlite/i
        scope = sluggable_class.unscoped.where(base, normalized, wildcard)
        scope = scope.where("#{pkey} <> ?", value) unless sluggable.new_record?
    
        length_command = "LENGTH"
        length_command = "LEN" if sluggable.connection.adapter_name =~ /sqlserver/i
        scope = scope.order("#{length_command}(#{column}) DESC, #{column} DESC")
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2011-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多