ruby/rails: How to determine if module is included?

module, ruby, ruby-on-rails

Solution

If I understand your question correctly, you can use `Module#include?`:

Man.include?(Features)

For example:

module M
end

class C
  include M
end

C.include?(M) # => true

Other ways

Checking `Module#included_modules`

This works, but it's a bit more indirect, since it generates intermediate `included_modules` array.

C.included_modules.include?(M) # => true

since `C.included_modules` has a value of `[M, Kernel]`

Checking `Module#ancestors`

C.ancestors.include?(M) #=> true

since `C.ancestors` has a value of `[C, M, Object, Kernel, BasicObject]`

Using operators like `<`

The `Module` class also declares several comparison operators:

- `Module#<`

- `Module#<=`

- `Module#==`

- `Module#>=`

- `Module#>`

Example:

C < M # => true 

Problem

Expanding on my question here (ruby/rails: extending or including other modules), using my existing solution, what's the best way to determine if my module is included? What I did for now was I defined instance methods on each module so when they get included a method would be available, and then I just added a catcher (`method_missing()`) to the parent module so I can catch if they are not included. My solution code looks like: ``` 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 ``` So in my models I have: ``` # 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 ``` And then I can ``` Man.new.can_walk? # => true Car.new.can_run? # => true Car.new.can_walk? # method_missing catches this # => false ``` Did I write this correctly? Or is there a better way?

Original source