En développant ma question ici ( Ruby/Rails: extension ou inclusion d'autres modules ), en utilisant ma solution existante, quelle est la meilleure façon de déterminer si mon module est inclus?
Ce que j'ai fait pour l'instant, c'est que j'ai défini des méthodes d'instance sur chaque module, donc lorsqu'elles sont incluses, une méthode sera disponible, puis j'ai simplement ajouté un capteur (method_missing()
) au module parent afin que je puisse détecter si elles ne sont pas inclus. Mon code de solution ressemble à:
module Features
FEATURES = [Running, Walking]
# include Features::Running
FEATURES.each do |feature|
include feature
end
module ClassMethods
# include Features::Running::ClassMethods
FEATURES.each do |feature|
include feature::ClassMethods
end
end
module InstanceMethods
def method_missing(meth)
# Catch feature checks that are not included in models to return false
if meth[-1] == '?' && meth.to_s =~ /can_(\w+)\z?/
false
else
# You *must* call super if you don't handle the method,
# otherwise you'll mess up Ruby's method lookup
super
end
end
end
def self.included(base)
base.send :extend, ClassMethods
base.send :include, InstanceMethods
end
end
# lib/features/running.rb
module Features::Running
module ClassMethods
def can_run
...
# Define a method to have model know a way they have that feature
define_method(:can_run?) { true }
end
end
end
# lib/features/walking.rb
module Features::Walking
module ClassMethods
def can_walk
...
# Define a method to have model know a way they have that feature
define_method(:can_walk?) { true }
end
end
end
Donc dans mes modèles j'ai:
# Sample models
class Man < ActiveRecord::Base
# Include features modules
include Features
# Define what man can do
can_walk
can_run
end
class Car < ActiveRecord::Base
# Include features modules
include Features
# Define what man can do
can_run
end
Et puis je peux
Man.new.can_walk?
# => true
Car.new.can_run?
# => true
Car.new.can_walk? # method_missing catches this
# => false
Ai-je bien écrit cela? Ou existe-t-il une meilleure façon?
Si je comprends bien votre question, vous pouvez le faire:
Man.included_modules.include?(Features)?
Par exemple:
module M
end
class C
include M
end
C.included_modules.include?(M)
#=> true
comme
C.included_modules
#=> [M, Kernel]
D'autres moyens:
comme @Markan l'a mentionné:
C.include? M
#=> true
ou:
C.ancestors.include?(M)
#=> true
ou juste:
C < M
#=> true