rubyベストプラクティスchapter8.4

コメントで指摘してもらった誤字を修正しました。ご指摘ありがとうございました。
[2012-08-03 Fri]

gemでのプロジェクト管理。今ようやく自分用のライブラリもgemにした方が楽かも?って思いはじめて、gem作っていたけど、bundlerにおまかせだったので勉強になります。

gemspecの書き方

gemに入れるべきファイルの指定方法
File.open('REVISION', 'w') { |f| f.puts "(unknown)" } unless File.exist?('REVISION')
readmes = FileList.new('*') do |list|
  list.exclude(/(^|[^.a-z])[a-z]+/)
  list.exclude('TODO')
  list.include('REVISION')
end.to_a

ここでやっていることは小文字のファイルとTODOファイルを削除して、readmesといる変数に入れておきます。hamlではライセンスとかのドキュメント類は大文字のファイル名に統一しているようです。
これも他のrubyプロジェクトも同じような気がする。

その後

spec.files = FileList['rails/init.rb', 'lib/**/*', 'bin/*', 'test/**/*', 'extra/**/*', 'Rakefile', 'init.rb'].to_a + readmes

として、必要な他のファイルをgemspecに教えてあげています。

testファイルも実行ファイルも同様にして、ファイルの命名規約にしたがってそれぞれgemspecに教えています。

ここのところはbundlerは

s.files = `git ls-files`.split("\n")

としていて、gitの管理ファイルをgemに入れるファイルとしているのであんまり意識してなかった。
bundlerにおまかせで困らないけど知っているといないとってなんか違うなぁ。

ただ、

gem install haml --tests

ってgemのインストールの際にtestを実行する場合、うまく動かないことが多いみたい。
依存関係とかライブラリパスとかをしっかり管理しないといけないみたい。
なのでテストをしたかったら、ちゃんとソースからとってrake testってした方が楽だと思う。

rdocについて

gemspecにrdocのオプションを指定するとgem serverとした時のrdocを制御出来る。

rdocはlibディレクトリ内のファイルを含めるだけなので、readmeの指定をしてあげて、タイトルを指定して、トップに来るファイル(だいたいreadme)を指定してあげてって感じ。
本に載っていたソースはこんな感じ

spec.has_rdoc = true
spec.extra_rdoc_files = readmes
spec.rdoc_options += [
  '--title', 'Haml',
  '--main', 'README.rdoc',
  '--exclude', 'lib/haml/buffer.rb',
  '--line-numbers',
  '--inline-source'
]

依存関係について

gemspecへの記載方法。

Gem::Specification.new do |spec|
  # ...省略
  spec.add_dependency('prawn-core', '~> 0.5.0')
  spec.add_dependency('prawn-layout', '~> 0.2.0')
  spec.add_dependency('prawn-format', '~> 0.1.0')
end

ここの3行が依存関係の記載。

  • '~> 0.5.0' 0.5系のバージョン
  • '>=' 指定バージョン以降
  • '>' 指定バージョンより上
  • '=' 指定されたバージョンのみ

という意味になります。なのでサンプルのprawn-coreの依存を別の表現にすると

spec.add_dependency('prawn-core', '>= 0.5.0', '< 0.6.0')

となります。
ちなみに何もバージョンを指定しないと、バージョンはなんでもいいという意味。

本で推奨しているのは

spec.add_runtime_dependency 'hoge'
spec.development_dependency 'foo'

というように実行時に必要とされるgem(runtime_dependency)と、開発時に必要とされるgem(development_dependency)を明確に記述したほうがいいと言っています。
bundlerで自動生成されるgemspecも同じように書けと言っています。
このように書いておくとdevelopment_dependencyと指定しているgemは

gem install hoge --development

としない以外はインストールされないようになります。

rails3以降を利用しているとbundlerがGemfileを作成してそこに依存関係を記述するけど、bundlerを素で使用するとgemspecが自動生成されてGemfileにはgemspecを見ろって思われる記述があるだけになっています。
こんな感じ。

source "http://rubygems.org"

# Specify your gem's dependencies in hoge.gemspec
gemspec

いまいちbundlerとgemspecの依存関係のあつかい方がわからなかったけどgemspecに綺麗に書けばbundlerがよきにはからってくれるのかな?


Rubyベストプラクティス -プロフェッショナルによるコードとテクニック

Rubyベストプラクティス -プロフェッショナルによるコードとテクニック