检查 ruby​​ 类是不是在特定模块中

Posted

技术标签:

【中文标题】检查 ruby​​ 类是不是在特定模块中【英文标题】:Check if a ruby Class is in a particular Module检查 ruby​​ 类是否在特定模块中 【发布时间】:2020-06-05 08:46:31 【问题描述】:

我有一个带有controller.class == Admin::TeamsControllercontroller 对象。我可能也有类似controller.class == Admin::UsersController 的情况。现在我想检查一下这是不是真的:

controller.class.to_s.match?('Admin::')

也就是说,我想知道:这个对象是在Admin 模块命名空间中定义的类的吗?说清楚,结构是这样的吗?

module Admin
  module SomeOtherModulePerhaps
    class TeamsController
    end
  end
end

我的问题:有没有更好的 Ruby 方法来测试这个?将类转换为字符串,然后像这样进行正则表达式匹配,感觉有点 hacky。

编辑:

对于我受限的用例,我可以这样检查:

controller.class.to_s.split('::').first == 'Admin'

但这并不能完全解决其他人可能遇到的一般情况。例如,可能有像XyzAdmin::TeamsController 这样的情况,有人可能想要排除,但我的第一个解决方案会失败,或者Foo::Admin::TeamsController,有人可能想要包含,但我的第二个解决方案会失败。

我想找到更好的方法。

【问题讨论】:

【参考方案1】:

怎么用controller_path

https://api.rubyonrails.org/classes/AbstractController/Base.html#method-c-controller_path

controller_path.match?('admin')

【讨论】:

在我的情况下,我正在修改文件 config/initializers/lograge.rb 并有一个以 config.lograge.custom_payload do |controller| ... 开头的代码块,因此我可以访问 controller 对象但无法调用controller_path 方法。【参考方案2】:

怎么样

controller.class.const_defined?(:Admin)

返回真或假

【讨论】:

【参考方案3】:

您可以尝试使用Module#nesting,但它会返回相当意外的结果,具体取决于类是使用完全限定名称​​还是一组嵌套语句定义的。

毕竟,ruby 中的类名简单的常量,可以通过多种方式定义类名,例如:

module A
  def self.class!
    Class.new do |c|
      define_method :test do puts c.name end
    end
  end
end
A.const_set :C, A.class!
#⇒ A::C
A::C.new.test
#⇒ A::C

这大致意味着,有很多方法可以欺骗最好的检测机制。也就是说,我会选择最简单的。

controller.class.to_s.split('::')[0...-1].include?('Admin')

将计算任何出现的Admin,除非Admin 是类名链中的最后一个项。

【讨论】:

【参考方案4】:

Rails 自带module_parents:

module Admin
  module SomeOtherModulePerhaps
    class TeamsController
    end
  end
end

controller = Admin::SomeOtherModulePerhaps::TeamsController.new

controller.class.module_parents
#=> [Admin::SomeOtherModulePerhaps, Admin, Object]

controller.class.module_parents.include?(Admin)
#=> true

在底层,它使用Module#name,即"Admin::SomeOtherModulePerhaps::TeamsController"

【讨论】:

【参考方案5】:

我想知道:这个类的对象是在Admin 模块命名空间中定义的吗?

[...]

有没有更好的 Ruby 方法来测试这个?

类没有在模块中定义,因此,既没有好的方法也没有其他方法可以测试它。

当您在模块定​​义主体中编写类定义主体时,您不会在模块和类之间创建任何关系。唯一的关系是分配给类的常量和模块之间的关系,而不是类。

因此,由于这种关系不存在,因此您无法对其进行测试。

【讨论】:

以上是关于检查 ruby​​ 类是不是在特定模块中的主要内容,如果未能解决你的问题,请参考以下文章

Python——检查对象是不是是某个模块中任何类的实例

如何检查特定元素中是不是有值或其他类?

检查常量是不是已在 Ruby 类中定义的正确方法

如何检查哈希中是不是存在特定值?

如何检查元素是不是包含特定的类属性

Android POJO 类检查特定键是不是包含 Boolean 或 arraylist 值