J'ai une classe Ruby dans laquelle je veux inclure des méthodes de classe et d'instance. En suivant le modèle décrit aquí J'utilise actuellement ce qui suit :
class SomeObject
include SomeObject::Ability
def self.some_builder_method(params)
# use some_class_method ...
end
end
module SomeObject::Ability
module ClassMethods
def some_class_method(param)
# ...
end
end
def self.included(klass)
klass.extend(ClassMethods)
end
def some_instance_method
# ...
end
end
Je préfère ne pas faire deux modules séparés (l'un étant inclus et l'autre étant étendu), car toutes les méthodes de mon module s'emboîtent logiquement. D'un autre côté, ce modèle a) m'oblige à définir un module supplémentaire de type ClassMethods
et b) me demande d'écrire un module de type "boilerplate". self.included
pour chaque module.
Y a-t-il une meilleure façon de procéder ?
Edit 1 : J'ai trouvé un autre moyen, mais je ne suis pas sûr qu'il soit meilleur que le premier.
module Concern
def included(base)
# Define instance methods.
instance_methods.each do |m|
defn = instance_method(m)
base.class_eval { define_method(m, defn) }
end
# Define class methods.
(self.methods - Module.methods).each do |m|
unless m == __method__
base.define_singleton_method(m, &method(m))
end
end
end
end
module SomeModule
extend Concern
def self.class_m
puts "Class"
end
def instance_m
puts "Instance"
end
end
class Allo
include SomeModule
end
Allo.class_m # => "Class"
Allo.new.instance_m # => "Instance"