从模块内部访问类的包含名称空间 [英] Accessing a class's containing namespace from within a module

查看:79
本文介绍了从模块内部访问类的包含名称空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个模块,该模块除了其他功能外,还将向您将其混合到的类中添加一些通用的查找器"类型功能.问题:出于方便和美观的原因,我想在类的外部 中加入一些功能,与类本身的作用域相同.

I'm working on a module that, among other things, will add some generic 'finder' type functionality to the class you mix it into. The problem: for reasons of convenience and aesthetics, I want to include some functionality outside the class, in the same scope as the class itself.

例如:

class User
  include MyMagicMixin
end

# Should automagically enable:

User.name('Bob')   # Returns first user named Bob
Users.name('Bob')  # Returns ALL users named Bob 
User(5)            # Returns the user with an ID of 5
Users              # Returns all users

我可以在这些方法中实现功能 ,没问题.并且情况1(User.name('Bob'))很简单.但是,情况2–4需要能够在User之外创建新的类和方法. Module.included方法使我可以访问该类,但不能访问其包含范围.我没有在类或模块上看到的简单的父"类型方法. (对于名称空间,我的意思是,不是超类也不是嵌套模块.)

I can do the functionality within these methods, no problem. And case 1 (User.name('Bob')) is easy. Cases 2–4, however, require being able to create new classes and methods outside User. The Module.included method gives me access to the class, but not to its containing scope. There is no simple "parent" type method that I can see on Class nor Module. (For namespace, I mean, not superclass nor nested modules.)

我想做到这一点的最佳方法是在类的#name上进行一些字符串解析,以分解其名称空间,然后将字符串转换回常量.但这似乎很笨拙,考虑到这是Ruby,我觉得应该有一种更优雅的方式.

The best way I can think to do this is with some string parsing on the class's #name to break out its namespace, and then turn the string back into a constant. But that seems clumsy, and given that this is Ruby, I feel like there should be a more elegant way.

有人有想法吗?还是我只是为了自己的利益而变得太聪明了?

Does anyone have ideas? Or am I just being too clever for my own good?

推荐答案

在您的示例中,User只是一个指向Class对象的常量.当包含MyMagicMixin时,您可以轻松创建另一个常量指针:

In your example, User is just a constant that points to a Class object. You can easily create another constant pointer when MyMagicMixin is included:

module MyMagicMixin
  class <<self
    def self.included(klass)
      base.extend MyMagicMixin::ClassMethods
      create_pluralized_alias(klass)
    end

    private

    def create_pluralized_alias(klass)
      fq_name = klass.to_s
      class_name = fq_name.demodulize
      including_module = fq_name.sub(Regexp.new("::#{class_name}$", ''))
      including_module = including_module.blank? ? Object : including_module.constantize
      including_module.const_set class_name.pluralize, klass
    end
  end

  module ClassMethods
    # cass methods here
  end
end

当然,这不能回答您是否应该做这样的事情.

Of course this doesn't answer whether you should do such a thing.

这篇关于从模块内部访问类的包含名称空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆