3 votes

Ajouter des méthodes de classe par le biais de include

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"

4voto

coreyward Points 26109

Si je vous comprends bien, vous voulez juste utiliser ActiveSupport::Concern :

module PetWorthy
  extend ActiveSupport::Concern

  included do
    validates :was_pet, inclusion: [true, 'yes']
  end

  def pet #instance method
  end

  module ClassMethods
    def find_petworthy_animal
      # ...
    end
  end
end

class Kitty
  include PetWorthy
end

Kitty.find_petworthy_animal.pet

Vous n'avez pas besoin (évidemment, je l'espère) d'utiliser l'option included si vous n'avez pas de comportement à déclencher sur l'inclusion, mais je l'ai mis juste pour démontrer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X