我有一个小逻辑,它直接在页面上使用AJAX进行I18n'inplace translation'。因此我想拦截I18n.translate
我的调查让我对此 - 看起来干净整洁 - 逻辑:基于此SO Answer (Method Wrapping)以及一些“它如何运作”试验和错误
module I18n
extend Module.new {
old_translate=I18n.method(:translate)
define_method(:translate) do |*args|
InplaceTrans.translate(old_translate,*args)
end
alias :t :translate
}
end
和
module InplaceTrans
extend Module.new {
def translate(old_translate,*args)
Translator.new.translate(old_translate, *args)
end
}
end
Translator.new.translate()
只是一个特技,所以我不必在开发时重启rails服务器
以上所有工作都很好而且稳定,但我不知道我在做什么......
问题(S):
这是一种有效(且干净)的方法吗?
extend Model.new { ... }
做了什么?
extend Model.new DO ... END
有什么区别? (似乎在我的情况下什么都不做)
编辑:回答我自己:根据DO/END vs {}和问题末尾:
为什么InplaceTrans.translate
内的I18n.newly_defined_method()
会根据这个问题解析为anonymous module.translate
:
创建一个新的匿名模块。如果给出一个块,则传递给它 模块对象,并在此上下文中评估块 模块使用module_eval。
所以它有效,但我真的很想知道为什么!
(RoR 1.9.3,3.2)
编辑:部分答案
extend Module.new {}
演变为extend(Module.new {})
,而
extend Module.new do/end
演变为extend(Module.new) do/end
所以使用do / end,块绑定到extend的结果。如果你想使用do / end,你必须使用大括号:
extend(Module.new do/end)
与extend Module.new {}
答案 0 :(得分:1)
以下是我所发现的,我不知道是否还有其他(副作用)我不知道。
让我们从一个模块开始:
module NiceOne
def self.init_param(param)
@base_param=param
end
def self.read_param
@base_param
end
def util_func(in_string)
in_string+NiceOne.read_param
end
end
并让它包含在一个类中。
class HomeController < SiteController
...
include NiceOne
def sandbox
NiceOne.init_param(' the base param')
# later:NiceOne.write_other_param(' the other param')
puts NiceOne.read_param
#later: puts NiceOne.read_other_param
puts util_func('can we read')
end
end
所以util_func
&#39;移动&#39;进入HomeController,而自我方法&#39;不,我们都知道(或不);所以我们得到:
the base param
can we rad the base param
如果您现在手动延长NiceOne
&#34;&#34;那样:
module NiceOne
def self.write_other_param(param)
@base_param=param
end
def self.read_other_param
@base_param
end
end
并取消注释HomeController中的两行:
the other param
the other param
can we read the other param
到目前为止这么容易,而不是问题的答案,只是介绍
如果没有更优雅的方式,那就不是Ruby了:
我们保持HomeController
和NiceOne
(原始)不变,但更改手册&#39;延长&#39;到:
module NiceOneNicen
def write_other_param(param)
@base_param=param
end
def read_other_param
@base_param
end
end
module NiceOne
extend NiceOneNicen
end
我们得到与以前相同的输出。这两种方法移动&#39;进入({}} OneNice
,如utli_func
进入HomeController
。如果你想用你心爱的模块扩展多个模块,这很有用!
但是,如果我们只需要一次吗?不要对Namespace进行轮询,我们即时创建模块,即Module.new
。所以
module NiceOne
dummy=Module.new {
def write_other_param(param)
...
end
}
extend dummy
end
和最终
module NiceOne
extend Module.new {
def write_other_param(param)
...
end
}
end
如果问do/end
,我们可以使用它,如果我们不忘记括号......
module NiceOne
extend( Module.new do
def write_other_param(param)
...
end
end)
end
所以 - 回答最后一个问题:用Module.new&#34创建的匿名模块只存在很短的时间&#34;并且仅用于将其方法推入OneNice
所以你可以阅读
extend Module.new { .. }
喜欢
"put a self. before every method in following" { }