ruby,为什么在模块中使用模块?

时间:2014-04-04 21:40:02

标签: ruby-on-rails ruby devise

尝试使用设计执行RemoteAuthetication,我遇到了一个例子(几乎是官方的一个,因为设计wiki仅限于引用this document)。

实际实现身份验证算法的所有类都是" double"包含在Devise,Models或Devise,Strategies中。
这是Devise,Models示例:

module Devise
  module Models
    module RemoteAuthenticatable

      extend ActiveSupport::Concern

      def remote_authentication(authentication_hash)
        # Your logic to authenticate with the external webservice
      end

    end
  end
end

第一个问题:你如何解释一个红宝石新手(就像我一样),也许来自另一种语言,比如java,这种命名空间的基本原理是什么?
虽然不同风格的命名空间在编程语言中很常见,但这种使用它们的特殊方式对我来说有点新鲜。
在其他语言中,即使在实现接口或扩展由它提供的类时,也不会使用第三方库的相同命名空间(例如在这种情况下设计)

但是在这里我们看到设计本身,它的位,定义了

module Devise
  module Models
     module Authenticatable
     extend ActiveSupport::Concern
     ...
  end
end

第二个问题:这里的模块Authenticatable似乎扩展了另一个模块。我发现了很多关于类的文档,包括或扩展了其他模块,但没有扩展其他模块的模块。这是什么目的?

2 个答案:

答案 0 :(得分:2)

如果查看对象模型,Ruby模块会附加到类中的祖先链中。所以:

Module B; end
class A
  include B
end
A.ancestors # => A, B, etc.

现在当B扩展另一个模块时:

Module C
  def a_module_method; end
end
Module B; extend C; end

然后Ruby将a_module_method添加到祖先链中的类方法中。所以你可以这样做:

A.a_module_method

因此,这是一种让您访问模块方法的不同方法。一个很好的理由是将实例方法与类方法隔离开来。

答案 1 :(得分:2)

回复:问题1

命名空间提供组织。 Devise由几个集成到您的应用程序中的部分组成,例如。模型,控制器,验证逻辑等......

使用相同命名空间的原因可以是

  1. 保持相同的组织结构。
  2. 添加/编辑原始模块和/或类。 Ruby允许重新打开类或模块并覆盖或添加其他逻辑。因此,没有必要扩展/包含一个类/模块来修补自己的代码。
  3. 但是,在重新打开您不拥有的课程/模块时,您确实要小心。


    回复:问题2

    模块与Class非常相似( Class实际上是Module的子代,然后它上传到Object然后是BasicObject ),除了它们不能实例。但是,他们可以拥有方法,变量和所有爵士乐,并充当一个单一的对象。因此,模块可以自然地包含和扩展其他模块,以获得在包含或扩展的模块中使用的逻辑。


    Ruby Class DocsRuby Module Docs