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

Posted

技术标签:

【中文标题】ruby/rails:如何确定是不是包含模块?【英文标题】:ruby/rails: How to determine if module is included?ruby/rails:如何确定是否包含模块? 【发布时间】:2015-04-24 09:42:05 【问题描述】:

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

我现在所做的是我在每个模块上定义了实例方法,因此当它们被包含时,一个方法将可用,然后我只是向父模块添加了一个捕获器 (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

我写对了吗?还是有更好的办法?

【问题讨论】:

这个问题有点复杂,所以我不确定这是否是你要找的,但要检查是否包含模型,你可以这样做object.class.include? Module 您可以使用respond_to? 来检查方法是否可用。 【参考方案1】:

如果我正确理解您的问题,您可以使用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]

使用&lt; 等运算符

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

Module#&lt; Module#&lt;= Module#== Module#&gt;= Module#&gt;

例子:

C < M # => true 

【讨论】:

赞成C &lt; M 语法。你知道我在哪里可以了解这样的糖语法吗?我还没有找到与“Thinking in Java”相当的 Ruby 语言,这是对该语言的全面介绍。 @makhan,这是Module#<的方法。 @makhan 来自 Russ Olsen 的“Eloquent Ruby”是对 Ruby idoms 的一个很好(而且非常全面)的概述。 正确的代码是:Man.included_modules.include?(Features) 而不是 includes? 我试图编辑答案,但你需要更改超过 6 个字符才能编辑,这篇文章的其余部分看起来不错:-) 谢谢@Alexander。明显的改进。

以上是关于ruby/rails:如何确定是不是包含模块?的主要内容,如果未能解决你的问题,请参考以下文章

Ruby,Rails - 如何检查 var 是不是是电子邮件

Ruby/Rails 的神秘“未定义常量”问题

如何快速正确的安装 Ruby,Rails 运行环境 · Ruby China

如何快速正确的安装 Ruby,Rails 运行环境

Ruby / Rails——从哪里包含一个方法? [复制]

Ruby Rails - Cloud9 - (SocketError)