nifty の mobilebackend の API を Ruby で使う際、require で気づきがあったのでメモ。※結論はふんわりしてます。
mobilebackendAPI を Ruby で便利に使うためのライブラリ ncmb-ruby-client を install 。
ncmb-ruby-client 0.0.6
moongift/ncmb-ruby-client
簡単なテストコードを書いてみる。
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 している。
$:.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 はこんな特徴があるらしい。
- ロードパスからファイルを探してくる
- 拡張ライブラリもロードできる
- 拡張子.rb/.soを省略できる
- 同じファイルは二度以上ロードしない
今までは 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 するとロードパスを順番に探していくらしい。
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 コマンドについての記事を見つけた。
$ 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 で何かを呼んだときのロードパスとただロードパスを読んだ時に表示されるリストが違うことに気づく。
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
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
#=>/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
なんか増えてるー。で、最終的にある程度しっくり来る記事を見つけた。
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)." ってことらしい。
納得。