Archive for 3月, 2010

昨日今日のご飯

Read the rest of this entry »

プログラマーへ64の質問

標記の質問集に答えました。100の質問,昔流行って多少ウザかったですよね。。
Read the rest of this entry »

Object.const_getをハックした話

大変厳しい監視にも負けず、普通にRubyの話をします。

文字列のクラス名をクラスにするには、Rubyの場合evalとかもあるけれど(参照: Class.forNameはどう書くのか、コメントも)、 Object.const_get を使うのが一番安全な気がします。変なコードをねじ込まれてもNameErrorになるだけですし。

irb(main):001:0> Object.const_get("String")
#=> String
irb(main):002:0> Object.const_get("String").new
#=> ""

でもこれ、たとえば Net::HTTP みたいな名前空間付きのクラスを呼ぶとエラーになりますんよ。

irb(main):001:0> require 'net/http'
=> true
irb(main):002:0> Object.const_get("Net::HTTP")
NameError: wrong constant name Net::HTTP
	from (irb):2:in `const_get'
	from (irb):2

なので、以下のようなメソッドをつくりました。

nested_const_get.rb

1
2
3
4
5
6
7
8
9
10
class Object
  def self.nested_const_get(*args)
    stack = (args[0] =~ /::/) ? args[0].split("::") : args
    klass = Object
    while const = stack.shift
      klass = klass.const_get(const)
    end
    klass
  end
end
irb(main):001:0> require 'nested_const_get'
#=> true
irb(main):002:0> Object.nested_const_get("String")
#=> String
irb(main):003:0> require 'net/http'
#=> true
irb(main):004:0> Object.nested_const_get("Net::HTTP")
#=> Net::HTTP
irb(main):005:0> Object.nested_const_get("Net::HTTP").start("blog.udzura.jp", 80)
#=> #<Net::HTTP blog.udzura.jp:80 open=true>
irb(main):006:0> Object.nested_const_get("Net::HTTP::Get")
#=> Net::HTTP::Get
irb(main):007:0> Object.nested_const_get("Net::HTTP::Get::METHOD")
#=> "GET"

ハックというほどでもないですね。一応、何かの役に立つこともあろうかと。