拦截I18n翻译/什么扩展Module.new {....}呢?

时间:2014-07-09 16:17:54

标签: ruby ruby-on-rails-3.2

我有一个小逻辑,它直接在页面上使用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 {}

相同

1 个答案:

答案 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了:

我们保持HomeControllerNiceOne(原始)不变,但更改手册&#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" {  }