2015-02-23 69 views
12

使用我現有的解決方案在此擴展我的問題(ruby/rails: extending or including other modules),確定我的模塊是否包含在內的最佳方法是什麼?ruby​​/rails:如何確定是否包含模塊?

我現在所做的是我在每個模塊上定義了實例方法,所以當它們包含一個方法將可用,然後我只在父模塊中添加一個捕獲器(method_missing()),這樣我就可以捕獲它們,如果它們不是包括在內。我的解決方案的代碼如下所示:

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 

所以在我的模型有:

# 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 

,然後我可以

Man.new.can_walk? 
# => true 
Car.new.can_run? 
# => true 
Car.new.can_walk? # method_missing catches this 
# => false 

我有沒有正確寫的嗎?或者,還有更好的方法?

+1

現在的問題是有點令人費解,所以我不知道這是你在找什麼,但檢查如果包含模型,你可以使用'object.class.include?模塊' – makhan 2015-02-23 05:54:33

+0

你可以使用'respond_to?'來檢查一個方法是否可用。 – Lesleh 2015-02-23 06:20:11

回答

29

如果我正確理解你的問題,你可以這樣做:

Man.included_modules.include?(Features)? 

例如:

module M 
end 

class C 
    include M 
end 

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

C.included_modules 
    #=> [M, Kernel] 

其他方式:

爲@ Markan提到:

C.include? M 
    #=> true 

或:

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

或者只是:

C < M 
    #=> true 
+0

Upvoted for'C makhan 2015-02-23 08:29:01

+0

@makhan,這是[Module#<](http://ruby-doc.org//core-2.2.0/Module.html#method-i-3C)的方法。 – 2015-02-23 08:54:25

+0

@makhan Russ Olsen的「雄辯的紅寶石」是一個很好的(和qiet全面的)紅寶石idoms的概述。 – TNT 2016-02-05 10:10:50