名前空間付き定数対応のObject.cost_set

Object.const_getをハックした話 を参考に、Object.const_setもモジュールによる名前空間付き定数に対応させてみた。車輪の再発明をした気がしなくはないけど、そこは気にしない。


class Object
  def self.nested_const_get(name)
    stack = (name.is_a?(Array))  ? name : name.split("::")
    klass = Object
    while const = stack.shift
      klass = klass.const_get(const)
    end
    return klass
  end

  def self.nested_const_set(args = {})
    args.each do |name, value|
      stack = (name.is_a?(Array)) ? name : name.to_s.split("::")
      last_const = stack.pop

      klass = nested_const_get(stack)
      klass.const_set(last_const, value)
    end
  end
end

使い方は、

Object.nested_const_set("Foo::Bar" => "foooo")

RSpec: Stubbing RAILS_ENV and other constantsのように、一時的に定数を換えたいという場合に使えると思う。

ただしまだテストはしていない :)