公私含めて2年間でたぶん30個以上はgemを作ってますが、なんとなく体得はしたもののこういうことは誰も教えてくれなかった気がするので残しておきます
アンダースコアとハイフンを使い分ける
gemを作る第一歩は
bundle gem <作りたいgemの名前>
ってやると思いますが、単語区切りであればアンスコ、ネームスペースの区切りだったらハイフンを使います
アンダースコア区切り
$ bundle gem go_princess_precure Creating gem 'go_princess_precure'... create go_princess_precure/Gemfile create go_princess_precure/.gitignore create go_princess_precure/lib/go_princess_precure.rb create go_princess_precure/lib/go_princess_precure/version.rb create go_princess_precure/go_princess_precure.gemspec create go_princess_precure/Rakefile create go_princess_precure/README.md create go_princess_precure/bin/console create go_princess_precure/bin/setup create go_princess_precure/.travis.yml create go_princess_precure/.rspec create go_princess_precure/spec/spec_helper.rb create go_princess_precure/spec/go_princess_precure_spec.rb Initializing git repo in /Users/sue445/tmp/go_princess_precure
go_princess_precureで1階層
ハイフン区切り
$ bundle gem go-princess-precure Creating gem 'go-princess-precure'... create go-princess-precure/Gemfile create go-princess-precure/.gitignore create go-princess-precure/lib/go/princess/precure.rb create go-princess-precure/lib/go/princess/precure/version.rb create go-princess-precure/go-princess-precure.gemspec create go-princess-precure/Rakefile create go-princess-precure/README.md create go-princess-precure/bin/console create go-princess-precure/bin/setup create go-princess-precure/.travis.yml create go-princess-precure/.rspec create go-princess-precure/spec/spec_helper.rb create go-princess-precure/spec/go/princess/precure_spec.rb Initializing git repo in /Users/sue445/tmp/go-princess-precure
go, princess, precureで計3階層
分かりやすい説明
ハイフンとアンダースコアの使い分け - 暁 [stfuawsc]
runtime dependency と development dependencyは使い分ける
こういうの
spec.add_dependency "activesupport", ">= 4.0.0" spec.add_development_dependency "rspec"
(add_dependency
は add_runtime_dependency
へのaliasなので同じもの)
- gemの実行に必要なものは
add_dependency
に書く(runtime dependency)- 例:activesupport, activerecordなど
- 何をするgemなのかによってruntime dependencyは変わる。( 他のgemに依存していなければ
add_dependency
が無いこともある)
- そのgemの開発だけに必要なものは
add_development_dependency
に書く (development dependency)
依存性は最小限にする(gem)
例えばactivesupportの機能を使いたくてgemspecに
# bad example spec.add_dependency "rails"
と書いていると他のフレームワークでは使えないのかなと思ってしまうので
# good example spec.add_dependency "activesupport"
のように本当に必要なgemのみを書いた方がいいです
依存性は最小限にする(バージョン)
# bad example spec.add_dependency "activesupport", "4.2.1"
みたいにバージョンを固定してしまうとアプリ側で他のバージョンと組み合わせて使うことができないので、add_dependency
に関しては基本的にはバージョンは書かなくていいと思います。*1
# good example spec.add_dependency "activesupport"
また、「このバージョンで追加された機能に依存しているんだ!」という場合にはバージョンの下限を書くといいです
# good example spec.add_dependency "activesupport", ">= 4.2.0"
テストを書く
OSSとして公開するのであれば可能な限りユニットテストは必須だと思います。*2
理由:gemの正しい振る舞いを他の人が確認できるようにするため
- 人のリポジトリをforkして機能を追加したい時に、テストが無いと自分の修正でgemの既存の機能を壊してしまう(デグレ)のではないかと不安になります
- 全くテストがないリポジトリに対して整備されたPullRequestしてくれるって可能性も0ではないですが、PullRequest送ってくれる人がよっぽどのテストマニア*3じゃないとやってくれないと思います。
- ユニットテストという形で手軽に動作確認できる環境を用意しておくのは個人的には「おもてなし」だと思います
デファクトスタンダードに従う
さっきの「テストを書く」とも関連。
- specディレクトリやtestディレクトリにテストコードがある
rake test
を叩けばテストを実行できる- binディレクトリの実行ファイルを
--help
をつけて実行すればコマンド一覧が表示される
よくある構成ですが、こういうよくある構成にすることで他の人がforkした時の学習コストが抑えられます。
以前見たとあるリポジトリだと、exampleディレクトリの中に動作確認用のスクリプトがあってそれを実行することで目視で動作確認を行っている形跡がありましたが、こういう特殊な構成だと誰もforkできないのではないかと思います・・・w
エントリ冒頭で紹介した bundle gem
コマンドで作っていればだいたいデファクトスタンダートな構成になるので、 bundle gem
コマンドを使ってgemを作ることが「デファクトスタンダートに従う」の第一歩だと思います。(うまくまとまった)