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 中的行为,它会产生非常奇怪的结果,因为它仍然是仅在包含模块时进行评估。
这可能是一个非常简单的问题,但我想关心的是添加了一个验证,其参数取决于派生 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 中的行为,它会产生非常奇怪的结果,因为它仍然是仅在包含模块时进行评估。