Rails 关注 class_macro 继承自 class 的参数

Rails Concern class_macro with params from inherited class

这可能是一个非常简单的问题,但我想关心的是添加了一个验证,其参数取决于派生 class 中的方法。例如,我想关注 SlugHelpers 如下

module SlugHelpers
  extend ActiveSupport::Concern


  included do
     validates :slug, uniqueness: { case_sensitive: false, message: "Slug must be unique", scope: slug_scope }, presence: true,

  end

  class_methods do
    def slug_scope
      []
    end
  end

end

然后有一个模型 Post 覆盖 slug_scope,例如,

class Post < ApplicationRecord
  include SlugHelpers

  def self.slug_scope
     [:stream_id, :stream_type]
  end

我希望 Post 中定义的 slug_scope 覆盖包含的 do 中使用的 slug_scope (尽管我可能调用错了,也许我需要 self.class.slug_scope ) 但正如所写,我认为这行不通(包含的 do 不是在派生的 class 定义其方法之前执行的)吗?

我可以使用前置的 do 以某种方式做到这一点吗?或者我写这个的方式大致正确吗?我知道包含的模块在派生 class 之前进入继承链,但我显然对执行包含的 do 块中的 when/where 代码有点困惑。

如@mu_is_too_short 所述,您只需创建一个 class 方法,在调用时将验证添加到 class:

module SlugHelpers
  extend ActiveSupport::Concern
  class_methods do
    def has_slug(name = :slug, scope: :default_value)
        validates_uniqueness_of name, 
           case_sensitive: false, 
           message: "Slug must be unique", 
           scope: scope
        validates_presence_of name
    end
  end
end

这是 Ruby 中通常首选的方式,可以使模块提供的行为可配置。

class Foo
  include SlugHelpers
  has_slug(scope: [:foo, :bar])
end 
class Bar
  include SlugHelpers
  has_slug(scope: [:baz, :bar])
end 

虽然您实际上可以在包含模块时在 class 上调用一个方法,但如果您想覆盖 subclasses 中的行为,它会产生非常奇怪的结果,因为它仍然是仅在包含模块时进行评估。