简体   繁体   English

ruby/rails:如何确定是否包含模块?

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

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?在这里扩展我的问题( ruby/rails:扩展或包含其他模块),使用我现有的解决方案,确定是否包含我的模块的最佳方法是什么?

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.我现在所做的是在每个模块上定义实例方法,这样当它们被包含时,一个方法将可用,然后我只是向父模块添加了一个捕获器( method_missing() ),这样我就可以捕获它们是否不包含。 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?如果我正确理解您的问题,您可以使用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检查Module#included_modules

This works, but it's a bit more indirect, since it generates intermediate included_modules array.这是有效的,但它有点间接,因为它生成中间的included_modules数组。

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

since C.included_modules has a value of [M, Kernel]因为C.included_modules的值为[M, Kernel]

Checking Module#ancestors检查Module#ancestors

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

since C.ancestors has a value of [C, M, Object, Kernel, BasicObject]因为C.ancestors的值为[C, M, Object, Kernel, BasicObject]

Using operators like <使用像<

The Module class also declares several comparison operators: Module类还声明了几个比较运算符:

Example:例子:

C < M # => true 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM