jewelerとgithubで始める初めてのRubyGem作成
WebJourney用に新しく開発したCouchDB用のデータマッパー"CouchResource"ですが、ちゃんと公開しないとガラパゴスになりそうなので、RubyGem として利用できるようにしよう、と決心をして作業を始めました。
上記スペックの人間が、jewelerというgemの存在を知り、試用してみたら、[これはべんり]だったので記録しておきます。
- まず jeweler をインストール
「jeweler って何?」っていう話ですが http://github.com/technicalpickles/jeweler/tree/master にあります。githubでRubyGemを成果物にするプロジェクトで役立つヘルパー。ということでインストール。
$ gem sources -a http://gems.github.com $ sudo gem install technicalpickles-jeweler
- github の設定を ~/.gitconfig に書き込む
git config --global コマンドで user.name, user.email などは設定済みですが、github.user, github.token を設定します。github.user は github のアカウント名、github.token は API Tokenです。自分のアカウントページを見ると、
Your User Information Username: yssk22 API Token: XXXXXXXXXXXXXXXXXXXXXXX
な具合で記載されているので、この値をgit config --global コマンドで設定します。
$ git config --global github.user yssk22 $ git config --global github.token XXXXXXXXXXXXXXXXXXXXXXX # 一応確認するとこんな感じになってます。 $ cat ~/.gitconfig [user] name = Yohei Sasaki email = yssk22 at gmail.com [github] user = yssk22 token = XXXXXXXXXXXXXXXXXXXXXXX
- jeweler を使ってリポジトリの作成
jeweler をインストール済みの環境であれば jeweler コマンドが使えます。これを使ってローカルリポジトリを作るのです。今回は couch_resource というプロジェクトを作ります。また、Ruby標準のTest::Unitでテストケースを作成しているので --testunit を引数に渡します。--rspec などもできるようです。--create-repo を使うとリポジトリの作成(+gemの有効化)もしてくれるようなのですが、既にリポジトリは手作業で作ってしまったので、よく分かりません。
$ jeweler couch_resource --testunit create .gitignore create Rakefile create LICENSE create README.rdoc create lib create lib/couch_resource.rb create test create test/test_helper.rb create test/couch_resource_test.rb Jeweler has prepared your gem in couch_resource
はい、couch_resourceディレクトリができました。このディレクトリでRakeを叩くとこんな感じでいろいろタスクがあります。
$ rake -T (in /Users/yssk22/project/couch_resource) rake VERSION.yml # Setup initial version of 0.0.0 rake build # Build gem rake clobber_rdoc # Remove rdoc products rake gemspec # Generate and validates gemspec rake gemspec:generate # Generates the gemspec, using version from VERSIO... rake gemspec:validate # Validates the gemspec rake install # Install gem using sudo rake rdoc # Build the rdoc HTML Files rake release # Release the current version. rake rerdoc # Force a rebuild of the RDOC files rake test # Run tests rake version # Displays the current version rake version:bump:major # Bump the gemspec by a major version. rake version:bump:minor # Bump the gemspec by a minor version. rake version:bump:patch # Bump the gemspec by a patch version. rake version:setup # Setup initial version of 0.0.0 rake version:write # Writes out an explicit version.
これは便利!!!Rakefile の中身を抜粋するとこんな感じになってます。
begin require 'jeweler' Jeweler::Tasks.new do |gem| gem.name = "couch_resource" gem.summary = %Q{TODO} gem.email = "yssk22 AT gmail.com" gem.homepage = "http://github.com/yssk22/couch_resource" gem.authors = ["Yohei Sasaki"] # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings end rescue LoadError puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" end
で、ワークフローは、githubのjewelerのREADMEには、
Hack, commit, hack, commit, etc, etc
とありますから、ここでもう自分のソースを追加ですね。自分の場合は既にソースはあるので、そこからlib, test などにソースを追加しました。
で、とりあえずは rake test かと思って、
$ rake test (in /Users/yssk22/project/couch_resource) Loaded suite /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake/rake_test_loader Started F Finished in 0.000915 seconds. 1) Failure: test_something_for_real(CouchResourceTest) [./test/couch_resource_test.rb:5]: hey buddy, you should probably rename this file and start testing for real. 1 tests, 1 assertions, 1 failures, 0 errors rake aborted! Command failed with status (1): [/opt/ruby-enterprise-1.8.6-20081215/bin/ru...] (See full trace by running task with --trace)
あう。2つ問題。
- couch_resource_test.rb は自分の作ったファイルではなく、jeweler が生成した初期テスト。必ず失敗するようになっている。
- そもそも 1 tests, 1 assertions というのがあり得ない。test タスク修正必要。
Rakefile 内の Rake::TestTask の定義を見ると、
Rake::TestTask.new(:test) do |test| test.libs << 'lib' << 'test' test.pattern = 'test/**/*_test.rb' test.verbose = false end
となっているので修正。*_test.rb というファイル名は好かんのです。test_*.rbがいいです(その方がtab補完が便利に使えるケースが多いので)。
Rake::TestTask.new(:test) do |t| t.libs << 'lib' << 'test' test.pattern = 'test/**/test_*.rb' t.verbose = true end
さて、これでテストも通ったので、いよいよリリースです。gemとかよく分からないけれどとりあえずspecは必要だろうと、rake gemspec を発行。
$ rake gemspec (in /Users/yssk22/project/couch_resource) Created VERSION.yml: 0.0.0 Generated: couch_resource.gemspec couch_resource.gemspec is valid.
VERSION.yml: 0.0.0 ってww
$ cat VERSION.yml --- :major: 0 :minor: 0 :patch: 0
せめて、0.1.0 ぐらいにはしよう、と思って、
$ rake version:bump:minor (in /Users/yssk22/project/couch_resource) Current version: 0.0.0 Updated version: 0.1.0 $ cat VERSION.yml --- :major: 0 :minor: 1 :patch: 0
OK。これで再び rake gemspec を実行し、生成されたgemspecを見ます。
$ cat couch_resource.gemspec # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = %q{couch_resource} s.version = "0.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Yohei Sasaki"] s.date = %q{2009-03-10} s.email = %q{yssk22@gmail.com} s.extra_rdoc_files = ["README.rdoc", "LICENSE"] s.files = ["README.rdoc", "VERSION.yml", "lib/couch_resource", "lib/couch_resource/base.rb", "lib/couch_resource/callbacks.rb", "lib/couch_resource/connection.rb", "lib/couch_resource/error.rb", "lib/couch_resource/struct.rb", "lib/couch_resource/validations.rb", "lib/couch_resource/view.rb", "lib/couch_resource.rb", "test/test_base.rb", "test/test_callbacks.rb", "test/test_connection.rb", "test/test_struct.rb", "test/test_validations.rb", "LICENSE"] s.has_rdoc = true s.homepage = %q{http://github.com/yssk22/couch_resource} s.rdoc_options = ["--inline-source", "--charset=UTF-8"] s.require_paths = ["lib"] s.rubygems_version = %q{1.3.1} s.summary = %q{TODO} if s.respond_to? :specification_version then current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION s.specification_version = 2 if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then else end else end end
エクセレント!!!じゃ、gem作ろう。build タスクでgemがpkgディレクトリにできます。
$ rake build (in /Users/yssk22/project/couch_resource) WARNING: no rubyforge_project specified Successfully built RubyGem Name: couch_resource Version: 0.1.0 File: couch_resource-0.1.0.gem mac:couch_resource yssk22$ ls pkg couch_resource-0.1.0.gem << すげー。install タスクを使うと、生成されたgemをローカルにインストールできるようです。 >|| $ rake install (in /Users/yssk22/project/couch_resource) Executing "sudo gem install ./pkg/couch_resource-0.1.0.gem": Password: Successfully installed couch_resource-0.1.0 1 gem installed Installing ri documentation for couch_resource-0.1.0... Installing RDoc documentation for couch_resource-0.1.0...
ついでに、動くか試してみます。
$ irb irb(main):001:0> require 'rubygems' => true irb(main):002:0> require 'couch_resource' => true irb(main):003:0> class TestCouch < CouchResource::Base irb(main):004:1> database = "http://localhost:5984/test_couch" irb(main):005:1> string :title irb(main):006:1> end => []
簡単gem化。さて、大丈夫そうなので、いい加減ソースのコミットをしましょうか。.gitignore を確認するといい具合に設定されてます。.DS_Store がある当たりMacも考慮。
$ cat .gitignore *1236626942*.sw? .DS_Store coverage rdoc pkg
ということで、気兼ねなく git add して、git commit しておきます。で push。jewelerでディレクトリを作った場合、remote add はいらないです*1。
で、gemspec なども追加されているので、最後にgithub側のリポジトリの設定で、リポジトリのWebコンソールにアクセスし(https://github.com/{user_name}/{repo_name}、edit を選択して、RubyGem のチェックボックスにチェックをします。
これで、github側でgemの生成をしてくれるようになり、ユーザー側のgemのソースに http://gems.github.com を追加している場合は、gem install {username}-{gemname} でインストールできるようになります。
gemの生成には少し時間がかかるようで、http://gems.github.com/list.html にリストされればreadyです。
さて、次にreleaseタスクの話になるわけですが(gem/push/tag付けの自動化)、とりあえずはいいや、ということでこのエントリはここまで。
それにしても、すばらしかった!
併せて読みたい:
http://d.hatena.ne.jp/secondlife/20080520/1211286537