21
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ruby 普段特に何も考えずに使っていた require について調べてみた

Last updated at Posted at 2016-05-06

nifty の mobilebackend の API を Ruby で使う際、require で気づきがあったのでメモ。※結論はふんわりしてます。
mobilebackendAPI を Ruby で便利に使うためのライブラリ ncmb-ruby-client を install 。

ncmb-ruby-client 0.0.6
moongift/ncmb-ruby-client

簡単なテストコードを書いてみる。

hoge.rb
require 'ncmb-ruby-client'

class NiftyMbaas
  NCMB_APP_KEY = 'hogehoge'
  NCMB_KEY = 'hogehogehoge'

  def initialize
    NCMB.initialize application_key: NCMB_APP_KEY,  client_key: NCMB_KEY
    @client =  NCMB::Client.new application_key: NCMB_APP_KEY,  client_key: NCMB_KEY
  end

  def hogehoge
    p @client
  end
end

nm = NiftyMbaas.new
nm.hogehoge

こんなエラーが出る。

/Users/home/.rbenv/versions/2.1.4/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- ncmb-ruby-client (LoadError)

ncmb-ruby-client を load できてないとエラーが出る。
gem install できているか確認してみる。

gem list | grep ncmb                                                                                                  
ncmb-ruby-client (0.0.6)

できているー。ということでgithubを確認。examples ファイルをよく見てみると ncmb のみで require している。

data_store.rb
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$:.unshift(File.dirname(__FILE__))
require 'rubygems'
require 'ncmb'
require 'yaml'
yaml = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'setting.yml'))
NCMB.initialize application_key: yaml['application_key'],  client_key: yaml['client_key']
@todo = NCMB::DataStore.new 'TestClass'
@todo = @todo.limit(20).count(1).skip(0)
# @todo = @todo.where(testKey: "testValue")
# puts "@todo[0] #{@todo[0]}"
puts "@todo[0].name #{@todo[0].message}"

ncmb-ruby-client/examples/data_store.rb

ということで試しに ncmb で require してみると上手くいく!

#<NCMB::Client:hoge @domain="mb.api.cloud.nifty.com", @api_version="2013-09-01",@application_key="hoge", @client_key="hogehoge">

ということで調べてみると、require はこんな特徴があるらしい。

  1. ロードパスからファイルを探してくる
  2. 拡張ライブラリもロードできる
  3. 拡張子.rb/.soを省略できる
  4. 同じファイルは二度以上ロードしない

第18章 ロード

今までは require は gem を require してきているイメージだったが、gem の中にある拡張子.rb/.so 等のファイルを探してきているみたいだ。先ほどの gem を見てみると、 ncmb-ruby-client.rb は無いが、ncmb.rb は lib の中にある。よく使うライブラリの nokogiri を見てもやはり nokogiri.rb がある。だんだんわかってきた。

そこでもう少しきちんと理解するためにロードパスについても調べてみた。

第18章 ロード インターフェース
[クエリ:$LOAD_PATH | るりまサーチ - Ruby](Kernel$$LOAD_PATH -> [String])

Rubyライブラリをロードするときの検索パスです。

どうやら require するとロードパスを順番に探していくらしい。

hoge.rb
p $LOAD_PATH
p $:
#=>/usr/local/Cellar/rbenv/HEAD/rbenv.d/exec/gem-rehash
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/site_ruby/2.1.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/site_ruby/2.1.0/x86_64-darwin15.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/site_ruby
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/vendor_ruby/2.1.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/vendor_ruby/2.1.0/x86_64-darwin15.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/vendor_ruby
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/2.1.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/2.1.0/x86_64-darwin15.0

とかで確認できる。で、これを順番に探していったのだが、なかなか探しているファイルが見つからない。nokogiri.rb でも ncmb.rb でも見つからない。で、今度はロードパスではなく、gemの場所で検索してみると、gem enviroment コマンドについての記事を見つけた。

【Ruby】Gemコマンドの使い方まとめ

$ gem environment 
RubyGems Environment:
  - RUBYGEMS VERSION: 2.6.2
  - RUBY VERSION: 2.1.4 (2014-10-27 patchlevel 265) [x86_64-darwin15.0]
  - INSTALLATION DIRECTORY: /Users/home/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0
  - USER INSTALLATION DIRECTORY: /Users/home/.gem/ruby/2.1.0
  - RUBY EXECUTABLE: /Users/home/.rbenv/versions/2.1.4/bin/ruby
  - EXECUTABLE DIRECTORY: /Users/home/.rbenv/versions/2.1.4/bin
  - SPEC CACHE DIRECTORY: /Users/home/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /Users/home/.rbenv/versions/2.1.4/etc
  - RUBYGEMS PLATFORMS:

ここでハマる。gem environment で出てくる path と $LOAD_PATH で出てくる path が違う。
ぐぐってもわからないのでいろいろいじっていると、require で何かを呼んだときのロードパスとただロードパスを読んだ時に表示されるリストが違うことに気づく。

hoge.rb
puts $LOAD_PATH
#=>/usr/local/Cellar/rbenv/HEAD/rbenv.d/exec/gem-rehash
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/site_ruby/2.1.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/site_ruby/2.1.0/x86_64-darwin15.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/site_ruby
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/vendor_ruby/2.1.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/vendor_ruby/2.1.0/x86_64-darwin15.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/vendor_ruby
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/2.1.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/2.1.0/x86_64-darwin15.0
hoge.rb
require 'nokogiri'
puts $LOAD_PATH
#=>/usr/local/Cellar/rbenv/HEAD/rbenv.d/exec/gem-rehash
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/mini_portile2-2.0.0/lib
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/nokogiri-1.6.7.2/lib
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/extensions/x86_64-darwin-15/2.1.0-static/nokogiri-1.6.7.2
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/site_ruby/2.1.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/site_ruby/2.1.0/x86_64-darwin15.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/site_ruby
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/vendor_ruby/2.1.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/vendor_ruby/2.1.0/x86_64-darwin15.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/vendor_ruby
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/2.1.0
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/2.1.0/x86_64-darwin15.0
hoge.rb
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/mini_portile2-2.0.0/lib
#=>/Users/home/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/nokogiri-1.6.7.2/lib

なんか増えてるー。で、最終的にある程度しっくり来る記事を見つけた。

module Kernel

require(path)
When RubyGems is required, #require is replaced with our own which is capable of loading gems on demand.

When you call require 'x', this is what happens:

  • If the file can be loaded from the existing Ruby loadpath, it is.
  • Otherwise, installed gems are searched for a file that matches. If it's found in gem 'y', that gem is activated (added to the loadpath).

The normal require functionality of returning false if that file has already been loaded is preserved.

Also aliased as: gem_original_require

"the existing Ruby loadpath" からロードできる場合はするが、それ以外は "installed gems are searched for a file that matches. If it's found in gem 'y', that gem is activated (added to the loadpath)." ってことらしい。

納得。

21
18
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?