我正在开发一个模块,其中包括将一些通用的“finder”类型功能添加到您混合到的类中。问题:出于方便和美观的原因,我想将类之外的一些功能包括在与类本身相同的范围内。
例如:
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
方法允许我访问类,但不允许访问它的包含作用域。没有简单的“父”类型方法,我可以在类或模块上看到。(对于命名空间,我的意思是,不是超类或嵌套模块。)
我认为最好的方法是对类的#name
进行字符串解析,以打破其命名空间,然后将字符串转换为常量。但这似乎很笨拙,考虑到这是Ruby,我觉得应该有一种更优雅的方式。
有人有主意吗?还是我只是为了自己的利益太聪明了?
发布于 2010-03-20 15:20:43
在您的示例中,User
只是指向Class
对象的一个常量。当包含MyMagicMixin
时,可以轻松地创建另一个常量指针:
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
当然,这并不能回答你是否应该做这样的事情。
发布于 2010-03-20 04:02:50
我倾向于变得太聪明。
即使有一个优雅的解决方案,在中包含一个模块(一个在之外创建类的类)似乎也很奇怪。
发布于 2010-03-20 07:51:14
这是一个有时会出现在邮件列表上的问题。这也是Rails中出现的一个问题。解决方案是,正如您已经怀疑的,基本上是Regexp咀嚼。
但是,还有一个更根本的问题:在Ruby中,类没有名称!和其他类一样,类只是一个对象。您可以将其赋值给实例变量、局部变量、全局变量、常量,甚至根本不将其赋值给任何东西。Module#name
方法基本上只是一种方便的方法,其工作方式如下:它查看定义的常量列表,直到找到指向接收方的常数。如果它找到了一个,它会返回它能找到的第一个,否则它会返回nil
。
因此,这里有两种失效模式:
a = Class.new
a.name # => nil
B = a
B.name # => "B"
A = B
A.name # => "B"
Module#name
只返回它找到的的第一个名称
现在,如果有人试图调用As
来获取A
的列表,他们会很惊讶地发现这个方法并不存在,但是他们可以调用Bs
来获得相同的结果。
这在现实中确实发生了。例如,在MacRuby中,String.name
返回NSMutableString
,Hash.name
返回NSMutableDictionary
,Object.name
返回NSObject
。这是因为MacRuby将runtime和Objective运行时集成到一个运行库中,而且由于目标-C可变字符串的语义与runtime完全相同,所以runtime类的整个实现实际上是一行:String = NSMutableString
。由于MacRuby位于Objective之上,这意味着Objective首先启动,这意味着NSMutableString
首先被插入符号表,这意味着它首先由Module#name
找到。
https://stackoverflow.com/questions/2481775
复制相似问题