Rubyのrequireとrequire_relative

一昨日の同じディレクトリにある他の.rbファイルの読み込み方について、りょーさんからツッコミいただきました。

require_relative を使った方がよい場面があるんではなかったでしたっけ

https://twitter.com/beakmark/status/555112756727144448

requireでなくrequire_relativeを使う場合があるとのこと。

requireはカレントディレクトリからの相対パス、require_relativeは当該ファイルからの相対パスを記述するそうです。

自分は後者のつもりで前者を使おうとしていたので、誤りでした。

で、じゃあrequire_relativeをこれからは使うぞと思っていたところ、「require_relativeなんて使ってるの見たことねーぞ」と某所からツッコミを受けました。githubの言語別Trendに上がっているリポジトリを覗いて回ったところ、たしかに誰も使ってないですね^q^

ではどうやっているんだと思ったら。

ある特定のディレクトリ以下のライブラリを読み込みたい場合は、$LOAD_PATHに追加したほうが楽そうですね。

http://qiita.com/nekogeruge_987/items/2d18f388219597c75e05#comment-b8a83de723d5962a62a2
$LOAD_PATH << '/lib'
require 'filename'

あーRakefileの先頭とかでよく見るこれか。

$:.unshift( "lib" )

libディレクトリにコードをまとめておいて、まとめてLOAD_PATHに追加する。

この記述のおかげで、個別のファイルの中では相対パスで書かずに済むんですね。なるほど。

freezeできない「既存の定数」って何? - Effective Ruby

『Effective Ruby』を読んでのメモ。前回はこちら。

今日は2章の項目10まで読みすすめました。1章の続きを復習します。

項目4 定数がミュータブルなことに注意しよう

Rubyでは定数は書き換えられる値なので、書き換えられて困る値はfreezeしようという話。

配列の定数を使う場合は、配列自体と、配列の要素を両方freezeする必要がある。

疑問点

p.11の次の文章が、よく分からなかった。

定数をフリーズすれば、目立たず、追跡しにくいバグを例外に変えることができる。これは、明らかに大きなことだ。しかし、これではまだ十分ではない。定数が参照するオブジェクトをフリーズしても、既存の定数に新しい値を代入すれば、問題が起きる。

上の文章の「既存の定数」が何を意味しているのかが分からない。既存?

このくだりでは、次のようなサンプルコードで、「既存の定数」であるところのTIMEOUTという値に対して値を代入できてしまうことが示される。

irb(main):001:0> TIMEOUT=5
=> 5
irb(main):002:0> TIMEOUT += 5
(irb):2: warning: already initialized constant TIMEOUT
(irb):1: warning: previous definition of TIMEOUT was here
=> 10

ためしに定数TIMEOUT自体をfreezeするも、値を代入できてしまう。

irb(main):003:0> TIMEOUT.freeze
=> 10
irb(main):004:0> TIMEOUT += 5
(irb):4: warning: already initialized constant TIMEOUT
(irb):2: warning: previous definition of TIMEOUT was here
=> 15

定数TIMEOUTは直接freezeできない(しても意味がない?)ということは分かる。

本文では、moduleの中にTIMEOUTを定義して、module自体をfreezeするという対処法が述べられている。

項目5 実行時の警告に注意しよう

Rubyは、構文解析フェーズ(本文ではコンパイル時と呼んでいる)と実行フェーズの2つでコードを操作する。処理系のオプションを活用すると、それぞれのフェーズで別の種類の警告を表示できる。

-wオプションをつけることと、VERBOSE変数を使うことは、排他ではない。両方やれというのが筆者の主張。

警告を活用してコードを修正しよう、Rubyにコードの意図を推測させるのはやめよう、という話だった。

今日はここまで。第1章は終了。

Effective Ruby

Effective Ruby

Mac上でRubyのバージョンを2.0.0から2.2.0に上げる

Mac OS X(Yosemite)システム標準の2.0.0を使っていることが気になっていたので、バージョンを上げました。手順をメモ。

次の記事が参考になりました。

rbenvとruby-buildのインストール

Homebrewでrbenvとruby-buildをインストールする。

% brew install rbenv ruby-build

ruby-buildは、rbenvのプラグイン。rbenv以外のRubyの複数バージョン管理ツールと一緒に使ったり、ruby-build単独で使ったりもできるとのこと。

インストール直後に--versionを叩くとエラーになる。

% rbenv --version
/usr/local/Cellar/rbenv/0.4.0/libexec/rbenv---version: line 17: cd: /Users/USER_NAME/.rbenv: No such file or directory

rbenvのREADMEに書いてあるとおり、パスの設定をする。手元のシェルはzshなので、次のようにする。

% echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc
% echo 'eval "$(rbenv init -)"' >> ~/.zshrc

ターミナル(iTerm)を再起動する。

% rbenv --version
rbenv 0.4.0

今度はエラーが出ることなく、rbenvのバージョンを表示できた。

Rubyのインストール

バージョンを指定して、Rubyをインストールする。rbenv install --listで、インストール可能なRubyの一覧を確認できる。

% rbenv install 2.2.0

自分の環境で利用できるRubyのバージョンを確認すると、システムにプリインストールされているバージョンが、依然として優先されている。

% rbenv versions
* system (set by /Users/USER_NAME/.rbenv/version)
  2.2.0

カレントディレクトリでも同様。

% rbenv version
system (set by /Users/USER_NAME/.rbenv/version)

そこで、環境全体で使うRubyのバージョンを、先ほどインストールした2.2.0に変更する。

% rbenv global 2.2.0

これで、カレントディレクトリ、システム全体ともに、Ruby 2.2.0が使えるようになった。

% rbenv version
2.2.0 (set by /Users/USER_NAME/.rbenv/version)
% rbenv versions
  system
* 2.2.0 (set by /Users/USER_NAME/.rbenv/version)

わーい。