【问题标题】:How do I temporarily monkey with a global module constant?如何临时使用全局模块常量?
【发布时间】:2010-05-27 19:23:31
【问题描述】:

您好,

想修改全局memcache对象,发现如下问题。

  1. 缓存是一个常量
  2. 缓存是一个模块

我只想为一小部分代码全局修改 Cache 的行为,以获得可能的主要性能提升。

由于Cache是​​一个模块,我不能重新赋值,也不能封装。

我愿意这样做:

深入了解控制器方法...

code code code...

old_cache = Cache
Cache = MyCache.new

code code code...

Cache = old_cache

code code code...

但是,由于 Cache 是一个常量,我禁止更改它。线程目前不是问题。 :)

对我来说只是 alias_method 我需要的特殊代码是“礼貌”吗 只是为了一小段代码,然后再取消别名?那不 通过气味测试恕我直言。

有人有什么想法吗?

TIA,

-丹尼尔

【问题讨论】:

    标签: ruby-on-rails ruby metaprogramming


    【解决方案1】:

    但是您可以覆盖 Ruby 中的常量(无论是模块、类还是简单的其他对象):

    MyConst = 1
    
    # do stuff...
    
    old_my_const = MyConst
    MyConst = 5
    puts "MyConst is temporarily #{MyConst}"
    MyConst = old_my_const
    
    puts "MyConst is back to #{MyConst}"
    

    输出:

    a.rb:6:警告:已初始化常量 MyConst MyConst 暂时为 5 a.rb:8:警告:已初始化常量 MyConst MyConst 回到 1

    警告就是:警告。您的代码将继续运行。

    好的,在您的情况下,出于某种原因,这些警告可能是不可接受的。使用这个suppress_all_warnings method I've written。示例包括重新分配模块。

    def suppress_all_warnings
      old_verbose = $VERBOSE
      begin
        $VERBOSE = nil
        yield if block_given?
      ensure
        # always re-set to old value, even if block raises an exception
        $VERBOSE = old_verbose
      end
    end
    
    module OriginalModule
      MyConst = 1
    end
    
    module OtherModule
      MyConst = 5
    end
    
    def print_const
      puts OriginalModule::MyConst
    end
    
    print_const
    
    suppress_all_warnings do
      old_module = OriginalModule
      OriginalModule = OtherModule
    
      print_const
    
      OriginalModule = old_module
    end
    
    print_const
    

    现在您得到了正确的输出,但没有警告:

    1 5 1

    【讨论】:

    • 啊,我明白发生了什么事。我试图用类的实例替换常量,因此出现“动态常量分配”错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 2015-03-07
    • 2018-11-21
    • 1970-01-01
    • 2011-09-30
    • 2013-07-19
    相关资源
    最近更新 更多