web-dev-qa-db-ja.com

ruby / Rails:モジュールが含まれているかどうかを判断する方法は?

ここで私の質問を拡張して( 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

私はこれを正しく書きましたか?それとももっと良い方法がありますか?

27
index

私があなたの質問を正しく理解していれば、これを行うことができます:

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 
47
Cary Swoveland