ゼロから始めるgem生活

背景

周りでgemを作りたいという人は多いのですが、なんか大変そうといった印象で実際に手を動かすのに躊躇する人が多かったので、心理的ハードルを下げるために30分程度で0からgemを作るハンズオンをやりました。

これはそのときにやったことのメモで、現状これに沿って行っていけば簡単なgemを公開できるようになります。

ゴール

  • 簡単なgemを作成してrubygemsで公開するまで

事前準備

  • githubにアカウント作る
  • git pushで自分のリポジトリにpushできる状態
  • ruby 2.0以上
  • gem install bundler 済み
  • gem update –system 済み

名前決め

まずgemの名前を決めます。
他のgemと名前が被ってはいけないので、
https://rubygems.org/ で検索して無い名前をつける必要があります。

面倒な場合は、 nickname-hellor-world とかなら被りません。

今回は ota42y_test_gem で作るので、後は適度に読み替えてください。
namespaceの階層を合わせるため、区切り文字は_ではなく-を使ってください。

ひな形作成

bundle gem ota42y_test_gem -t
Creating gem 'ota42y_test_gem'...
Code of conduct enabled in config
      create  ota42y_test_gem/Gemfile
      create  ota42y_test_gem/lib/ota42y_test_gem.rb
      create  ota42y_test_gem/lib/ota42y_test_gem/version.rb
      create  ota42y_test_gem/ota42y_test_gem.gemspec
      create  ota42y_test_gem/Rakefile
      create  ota42y_test_gem/README.md
      create  ota42y_test_gem/bin/console
      create  ota42y_test_gem/bin/setup
      create  ota42y_test_gem/.gitignore
      create  ota42y_test_gem/.travis.yml
      create  ota42y_test_gem/.rspec
      create  ota42y_test_gem/spec/spec_helper.rb
      create  ota42y_test_gem/spec/ota42y_test_gem_spec.rb
      create  ota42y_test_gem/CODE_OF_CONDUCT.md

必要なファイル群ができます。
この中で、

  • ota42y_test_gem.gemspec
  • lib/ota42y_test_gem.rb
  • lib/ota42y_test_gem/version.rb

の3ファイルを今回は変更します。

必要事項の記入(gemspec)

ota42y_test_gem.gemspec を開きます。
だいたいこんな感じになっています。

lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "ota42y_test_gem/version"

Gem::Specification.new do |spec|
  spec.name          = "ota42y_test_gem"
  spec.version       = Ota42yTestGem::VERSION
  spec.authors       = ["ota42y"]
  spec.email         = ["[email protected]"]

  spec.summary       = %q{TODO: Write a short summary, because Rubygems requires one.}
  spec.description   = %q{TODO: Write a longer description or delete this line.}
  spec.homepage      = "TODO: Put your gem's website or public repo URL here."

todoと書かれているところを埋めていきます。
spec.summaryには一行サマリを、今回は ota42y test gemとかで。
spec.descriptionには眺めのサマリを、今回は my first gemとかで。
(ちゃんと作るときはちゃんと入れないと困ります)

spec.homepageには連絡先を書きます。
今回は http://github.com/username/gem_name で良いです。 (まだないですが後で作ります)

途中こんな感じの記述があります。

  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
  # to allow pushing to a single host or delete this section to allow pushing to any host.
  if spec.respond_to?(:metadata)
    spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
  else
    raise "RubyGems 2.0 or newer is required to protect against " \
      "public gem pushes."
  end

社内gemを不用意に外部公開しないために指定したhostにしかgemをreleaseできなくする機能がつきました。
なので公開範囲を区切りたい場合は適切に allowed_push_host を設定します。
が、今回はRubyGems.orgに出すのでここの記述をごっそり消します。

実装

これで公開するための準備が整ったので実装します。
lib/ota42y_test_gem.rb を開くと

require "ota42y_test_gem/version"

module Ota42yTestGem
  # Your code goes here...
end

こんな感じの空のmoduleが作られています。

今回は簡単のためにクラスメソッドを定義します。
各自好きな内容を書いてください

module Ota42yTestGem
  def self.honoka
    puts '⊂(・8・)⊃<ホノカチャァァァン!'
  end
end

試しに使ってみる

これで実装は完了しました。
RubyGems.orgにリリースすることもできますが、ここはいったんローカルで試してみましょう。

今回作ったgemのディレクトリと同じ階層にテスト用のフォルダを作ります。

わかりづらいですが最終的にこんな感じのディレクトリ構成になります。

- workspace
  - ota42y_test_gem
    - Gemfile
	  - lib
	    - ota42y_test_gem.rb
	  ....
  -  gem_test
    - Gemfile
	  - Gemfile.lock
    - my_gem_test.rb  

そしたらそのディレクトリに移動し、bundel initをしてGemfileを作ります。

cd my_gem_test.rb
bundle init

できたGemfileに以下の行を足します。

gem "ota42y_test_gem", path: "../ota42y_test_gem"

ここでpathのオブションには、そのGemfileからさっき作ったgemのフォルダへの相対パスを書きます。

かけたらbunle installをします。
これでローカルにあるgemを読み込むことができます。

bundle install
Using bundler 1.15.3
Using ota42y_test_gem 0.1.0 from source at `../ota42y_test_gem`
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

無事インストールできたら、gemを使う my_gem_test.rb ファイルを作ります。
内容は以下のようにさっき作ったメソッドを呼び出すだけです。

require 'ota42y_test_gem'

Ota42yTestGem.honoka

書けたら bundle exec ruby my_gem_test.rb でbundlerを使って実行します。

bundle exec ruby my_gem_test.rb
⊂(・8・)⊃<ホノカチャァァァン!

公開用にリポジトリを作る

無事動いたので実際に公開するために、githubでリポジトリを作ります。

bundlerでgemのひな形を作ったときにgitリポジトリも作られているので、
Initializeはせず空のリポジトリを作ります。

gemのディレクトリに移動後、コミットを行い、githubにpushします。

git add -A
git commit -m "first commit"

git remote add origin [email protected]:ota42y/ota42y_test_gem.git
git push -u origin master

RubyGems.orgにアカウントを作る

公開するためのアカウントを作ります。

https://rubygems.org/ に行ってアカウントを作ってください。
認証メールが届くはずなのでそれを使ってアカウントを有効にします。

適当なディレクトリでgem pushを実行し、ログインをしておきます。

リリースする

アカウントを作ったらリリースします。

リリースはgemspecのあるディレクトリで rake release を実行するだけです。

rake release
ota42y_test_gem 0.1.0 built to pkg/ota42y_test_gem-0.1.0.gem.
Tagged v0.1.0.
Pushed git commits and tags.
Pushed ota42y_test_gem 0.1.0 to rubygems.org.

問題なく終わればリリースできています。

自分のプロファイルページに行くと追加されているはずです
https://rubygems.org/profiles/username

インストールする

実際にインストールしてみます。
先ほど作った my_gem_test.rb のあるディレクトリに移動し、Gemflieを開きます。
さっき追加した行からpathといったオプションを消し、RubyGems.orgからインストールするようにします。

gem "ota42y_test_gem"

bundle installでgemをインストールし、 bundle exec ruby my_gem_test.rbを実行して問題なく動けば完了です!

その他

実際に何か機能を作る場合は以下のことを知っていれば進められると思います
(正確に言うといろいろ違いますが、凝ったことをしない限りはこの認識で問題無いです)

  • requireすると lib/ota42y_test_gem.rb だけがロードされる以外は普通のrubyファイルです
    • このファイル内で別ファイルをrequireすることで他のファイルもロードできます
  • versionを上げるときはlib/ota42y_test_gem/version.rbを書き換えます
    • 同じバージョンはrake releaseできません。
  • gem内で他のgemを使いたい場合は基本的にはGemfileではなくgemspecファイルに追加します
    • 標準でbundlerが設定されているので、同じような記述で増やせます