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?
If I understand your question correctly, you can useModule#include?
:
Man.include?(Features)
For example:
module M
end
class C
include M
end
C.include?(M) # => true
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]
Module#ancestors
C.ancestors.include?(M) #=> true
since C.ancestors
has a value of [C, M, Object, Kernel, BasicObject]
<
The Module
class also declares several comparison operators:
Example:
C < M # => true
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.