Rubyで名前空間が定義されているか確認する方法を調べている際、色々試した結果をメモしておきます。
方法1.Objectに対してconst_defined?を実行して調べる
これは駄目な方法。
method1.rb
module Hoge
module Foo
end
end
# 名前空間の書式で定数定義されている訳ではないので駄目.
puts Object.const_defined?("Hoge::Foo")
実行結果
method1.rb:7:in `const_defined?': wrong constant name Hoge::Foo (NameError)
from method1.rb:7:in `<main>'
方法2.defined?で定義済みか確認する
これは素直で良い方法。
method2.rb
module Hoge
module Foo
end
end
# 良い方法だが、名前空間を文字列でしか知らない場合に対応できない.
puts defined?(Hoge::Foo)
puts defined?(Hoge::Foo::Bar)
実行結果
constant
# `Hoge::Foo::Bar` は定義されていないので空文字列が返る
だが、仮に名前空間の情報が文字列でしか与えられていない場合、これでは対応できない。
方法3.名前空間を上から順番に定数定義されているかconst_defined?で調べる
ほぼほぼ無い要求かと思われるが、自分の場合、名前空間の情報を文字列でしか受け取ることができず、方法2を採用することができなかった。
そこで実施した苦肉の策が以下。
method3.rb
require "active_support"
require "active_support/core_ext"
module Hoge
module Foo
end
end
def defined_namespace?(full_namespace)
search_namespace = Object
full_namespace.split("::").each do |name|
return false unless search_namespace.const_defined?(name)
search_namespace = "#{search_namespace}::#{name}".constantize
end
true
end
puts defined_namespace?("Hoge::Foo")
puts defined_namespace?("Hoge::Foo::Bar")
実行結果
true
false
名前空間の定数を上から順番になめることで、定義されている名前空間か調べている。
これならば、文字列で名前空間の情報が与えられるケースでも対応することができる。
かなりレアケースかと思われるが、自分がまたハマった時のためにメモ。