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

标签 ruby-on-rails ruby module

在这里扩展我的问题 ( ruby/rails: extending or including other modules ),使用我现有的解决方案,确定我的模块是否包含在内的最佳方法是什么?

我现在所做的是在每个模块上定义实例方法,这样当它们被包含时,一个方法就可用,然后我只是向父模块添加一个捕获器 (method_missing())所以如果它们不包括在内,我可以 catch 。我的解决方案代码如下:

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

我写的对吗?或者有更好的方法吗?

最佳答案

如果我理解正确你的问题,你可以使用 Module#include? :

Man.include?(Features)

例如:

module M
end

class C
  include M
end

C.include?(M) # => true

其他方式

检查 Module#included_modules

这行得通,但有点间接,因为它会生成中间值 included_modules数组。

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

C.included_modules值为 [M, Kernel]

检查 Module#ancestors

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

C.ancestors值为 [C, M, Object, Kernel, BasicObject]

使用 < 这样的运算符

Module类还声明了几个比较运算符:

例子:

C < M # => true 

关于ruby-on-rails - ruby /rails : How to determine if module is included?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28667474/

相关文章:

ruby-on-rails - 有什么理由在使用 Mongoid 的 Rails 中避免单词 "type"?

ruby-on-rails -/为什么Rails 6仍在使用/推荐CoffeeScript?

ruby - 是否可以从一对多关系的 belongs_to 端使用 mongoid "nested attributes"?

包含 Fortran 中的子例程和函数的模块

ruby-on-rails - 如何获取has_many :through relation中的through实例

ruby-on-rails - rails : Paperclip & previews?

ruby-on-rails - 如何让 Rails 与 AngularJS 协同工作

ruby-on-rails - 虚拟属性和质量赋值

perl - 您建议使用哪个 Perl 模块来发送和接收电子邮件?

包含任何模块时的 Ruby 回调