This is probably a really easy question but I'd like to have a concern which adds a validation whose parameters depend on methods in the derived class. For instance, I'd like to have a concern SlugHelpers as follows
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
But then have a model Post which overrides slug_scope, e.g.,
class Post < ApplicationRecord
include SlugHelpers
def self.slug_scope
[:stream_id, :stream_type]
end
I want the slug_scope defined in Post to override the slug_scope used in the included do (though I might be calling that wrong, maybe I need self.class.slug_scope) but as written I think that this won't work (isn't the included do executed before the derived class defines its methods)?
Can I do this somehow using prepended do? Or is the way I wrote this roughly correct? I know that included modules are entered into inheritance chain before the derived class but I'm obviously kinda confused about when/where code in an included do block gets executed.
As described by @mu_is_too_short you can just create a class method which adds the validations to the class when called:
This is the generally preferred way in Ruby to make the behavior provided by modules configurable.
While you could actually call a method on the class when the module is included it would produce very strange results if you want to override the behavior in subclasses since it still would be evaluated just when the module was included.