gemの雛形からRubyプロジェクトの標準的なディレクトリ構造を確認する

id:sanematさんから、先日の書いた疑問について

$ bundle gem foo_bar-baz
で生成されるコードがルール的にだいたい標準よ

とコメントで教えていただいたので、さっそく確認しました。

bundlerのインストール

gemでbundlerをインストールする。最近のRubyがインストールされている環境なら、gemも標準で入っている。

gem install bundler

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

bundleとbundlerがインストールされた。

$ which bundle
/Users/USER_NAME/.rbenv/shims/bundle

$ which bundler
/Users/USER_NAME/.rbenv/shims/bundler

$ ls -la /Users/USER_NAME/.rbenv/shims/bundle*
-rwxr-xr-x  2 USER_NAME  staff  408  1 16 22:10 /Users/USER_NAME/.rbenv/shims/bundle
-rwxr-xr-x  2 USER_NAME  staff  408  1 16 22:10 /Users/USER_NAME/.rbenv/shims/bundler

2つがどう違うのか把握してないけど、次のコマンドを実行すると、いずれもBUNDLE(1)(bundle - Ruby Dependency Management)のマニュアルが開く。

$ bundler --help
$ bundle --help

なので、ひとまず気しない方向で。

gemの雛形で階層構造を確認する

gemの雛形を作る。

$ bundle gem foo_bar-baz
      create  foo_bar-baz/Gemfile
      create  foo_bar-baz/Rakefile
      create  foo_bar-baz/LICENSE.txt
      create  foo_bar-baz/README.md
      create  foo_bar-baz/.gitignore
      create  foo_bar-baz/foo_bar-baz.gemspec
      create  foo_bar-baz/lib/foo_bar/baz.rb
      create  foo_bar-baz/lib/foo_bar/baz/version.rb
Initializing git repo in /Users/USER_NAME/git/sandbox-rb/foo_bar-baz

(Gitリポジトリまで作ってくれるんですね)

階層構造の全体像を確認する。ちなみに、treeコマンドは、Mac OS Xにデフォルトで入っていないので、bundle install treebrew install treeでインストールする。

$ tree foo_bar-baz
foo_bar-baz
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── foo_bar-baz.gemspec
└── lib
    └── foo_bar
        ├── baz
        │   └── version.rb
        └── baz.rb
ルートディレクト

パスを解決するための記述は、foo_bar-baz.gemspecにあった。

lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'foo_bar/baz/version'

(1行目はよくわからないので置いといて)2行目はifdef感ある。この記述があるから、3行目で「foo_bar」から記述できるっぽい。

libディレクト

libディレクトリの下にfoo_barディレクトリがあり、スクリプトbaz.rbがある。

/lib/foo_bar/baz.rbには、Bazモジュールが定義されている。

require "foo_bar/baz/version"

module FooBar
  module Baz
    # Your code goes here...
  end
end

Bazモジュールは、FooBarモジュールの中に定義されている。

(このようにして名前空間を作るという話がEffective Rubyに書いてあった。あと、ディレクトリと名前空間を対応させるとも書いてあった)

つまり、モジュールFooBarと対応するように、foo_bazディレクトリが作られている。

bazディレクト

version.rbがあり、ここにもBazモジュールの定義がある。

module FooBar
  module Baz
    VERSION = "0.0.1"
  end
end

こちらのスクリプトにはrequireの記述がない。version.rbがモジュールの本体(?)で、baz.rb側が呼び出し側なんだろうか。

書かれている内容は、FooBar.Baz.VERSIONと呼ぶための定数定義ですね。

参考になりました! sanematさん、ありがとうございます。