从模块内部访问类的包含名称空间 [英] Accessing a class's containing namespace from within a module
问题描述
我正在开发一个模块,该模块除了其他功能外,还将向您将其混合到的类中添加一些通用的查找器"类型功能.问题:出于方便和美观的原因,我想在类的外部 中加入一些功能,与类本身的作用域相同.
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屋!