読者です 読者をやめる 読者になる 読者になる

Rubyにおけるライブラリロード

Ruby のライブラリロード周辺を理解してなかったので、調査&実験メモです。*1

環境

OSX Mavericks rbenv 0.4.0 + ruby 2.1.2

ロードパス を調べる

$: でも $LOAD_PATHでも同じ。

$ ruby -e 'puts $:'
/usr/local/Cellar/rbenv-gem-rehash/1.0.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/site_ruby/2.1.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/site_ruby/2.1.0/x86_64-darwin13.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/site_ruby
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/vendor_ruby/2.1.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/vendor_ruby/2.1.0/x86_64-darwin13.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/vendor_ruby
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/2.1.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/2.1.0/x86_64-darwin13.0

$ ruby -e 'puts $LOAD_PATH'
/usr/local/Cellar/rbenv-gem-rehash/1.0.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/site_ruby/2.1.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/site_ruby/2.1.0/x86_64-darwin13.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/site_ruby
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/vendor_ruby/2.1.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/vendor_ruby/2.1.0/x86_64-darwin13.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/vendor_ruby
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/2.1.0
/Users/kotaroito/.rbenv/versions/2.1.2/lib/ruby/2.1.0/x86_64-darwin13.0

requireする

http://docs.ruby-lang.org/ja/2.1.0/method/Kernel/m/require.html

require 'uri'

p URI.escape 'https://www.google.co.jp/search?q=るびー'

$: に格納されている PATHを順番に検索する。 手元では /Users/kotaroito/.rbenv/versions/2.1.2//lib/ruby/2.1.0/uri.rb をロードしていた。

ちなみに出力は

https://www.google.co.jp/search?q=%E3%82%8B%E3%81%B3%E3%83%BC

となる。

ここで 以下のファイルを用意して

# ./uri.rb 
class URI
    class << self
        def escape(url)
            'whoops'
        end
    end
end
require './uri'

p URI.escape 'https://www.google.co.jp/search?q=るびー'

とすると 出力は

whoops

となる。

サブディレクトリを指定した時はどうなるのか?

# .foo/bar.rb
class Buzz
   def initialize(name)
       @name = name
   end
end
require './foo/bar'

buzz = Buzz.new 'buzz'
p buzz

ロードできた。 同時に、パスとクラス名は必ずしも一致してる必要はないこともわかった。

実際、標準で用意されている Queue クラスは require ‘thread’ して使うようだ。

ネストしたクラス

# ./foo.rb
class Foo
    def hello
        'foo'
    end

end

class Foo::Bar
    def hello
        'bar'
    end
end
require './foo'

p Foo.new.hello  # => ‘foo'
p Foo::Bar.new.hello # => ‘bar'

と書ける。

# ./foo.rb
class Foo
    def hello
        'foo'
    end

    class Bar
        def hello
            'bar'
        end
    end
end

という書き方もできる。

module による名前空間

# ./foo.rb
module Foo
    class Bar
        def hello
            'bar'
        end
    end
end
require './foo'

p Foo::Bar.new.hello

moduleは名前空間を定義することにも使える。

まとめ

require, $LOADPATH, 名前空間について詳しくなりました。入門レベルとしてはここまでおさえておけば大丈夫な気がする(たぶん)。

See Also

Rails の autoload については、 Auto-loading lib files in Rails 4 - Stack Overflow に。

*1:Ruby を学習しはじめてから、まだ日が浅いです。