当然,要实现我在标题中的要求,可以编写如下代码:
module Foo
class << self
def included receiver
my_herd << receiver
end
def my_herd; @my_herd ||= [] end
alias where_everywhere_am_I_included my_herd
end
end
Foo.where_everywhere_am_I_included #=> []
module Bar
include Foo
end
Foo.where_everywhere_am_I_included #=> [Bar]
# etc.
我可以想象更糟糕的方法来做到这一点,例如搜索ObjectSpace
所有模块并 grep 他们的祖先。我想知道,有没有更好的方法?我是否忘记了某些东西,例如方法之类的东西Module#included_in
。我是否错过了一些聪明的东西,例如。著名的#append_features
方法?我有什么更好的选择?
编辑:我正在解决的现实世界问题与我的图书馆 SY有关,它提供了物理单位方法。物理单位方法,例如1.metre
, 1.m
, 1.s
, 1.lb
, 1.K
, 往往是容易发生冲突的简单符号。例如。ActiveSupport
已经定义了时间方法#hour
, #minute
, #second
on Numeric
。SY 还通过提供对单元方法的反应的 mixin来定义方法#hour
alias #h
、#minute
alias #min
、#second
alias #s
on 。但是使用的人已经定义了, ,因此不会加入。他们仍然可以通过,访问方法Numeric
#method_missing
ActiveSupport
#hour
#minute
#second
#method_missing
SY
#h
#min
,#s
缩写,但这不是重点。关键是,当 mixin 在包含它的模块中发现可能的冲突时,应该警告人们。这可以通过在Module#included
钩子中编码碰撞检查来简单地实现。但问题是用户也可以动态定义单位,比如:
PINT = Unit.of Volume, amount: 568.26.cm³
QUART = Unit.of Volume, amount: 2.pint
但是可以想象用户已经#quart
定义了方法Numeric
,在做其他事情,比如计算接收器的四分之一,或者返回相对于接收器的第四个音程等。所以当 ze 调用QUART = Unit#of...
构造函数时,我想问 mixinSY::ExpressibleInUnits
报告它在哪里混入,并在看到碰撞后发出警告Numeric
。我只是想让我的用户免于意外,我想知道什么是最有道德的(使用Avdi的商标词)。