2016年08月04日

「Gem」とは一体何なのか?

Railsを使い始めて半年ちょっと経ちますが、最近になって当たり前のように使っているGemが気になっています。
RailsとRubyを使い始めたその日から、空気のように当たり前に存在して、ほとんど意識することもなく何となくで使っていましたが、そろそろGemとは一体何なのかをはっきりさせておきたい気持ちです。

とりあえず "Gem" を生成してみる

よく知らないものを勉強するのならば、一度作ってみればいい!
と言うことで、bundlerさえ入っていればすぐにでも雛形を作れるようなのでやってみました。

[ Hakozaru ]% bundle gem gem_test

Creating gem 'gem_test'...
Do you want to generate tests with your gem?
Type 'rspec' or 'minitest' to generate those test files now and in the future. rspec/minitest/(none): rspec

Do you want to license your code permissively under the MIT license?
This means that any other developer or company will be legally allowed to use your code for free as long as they admit you created it. You can read more about the MIT license at http://choosealicense.com/licenses/mit. y/(n): y
MIT License enabled in config

Do you want to include a code of conduct in gems you generate?
Codes of conduct can increase contributions to your project by contributors who prefer collaborative, safe spaces. You can read more about the code of conduct at contributor-covenant.org. Having a code of conduct means agreeing to the responsibility of enforcing it, so be sure that you are prepared to do that. Be sure that your email address is specified as a contact in the generated code of conduct so that people know who to contact in case of a violation. For suggestions about how to enforce codes of conduct, see http://bit.ly/coc-enforcement. y/(n): y
Code of conduct enabled in config
      create  gem_test/Gemfile
      create  gem_test/.gitignore
      create  gem_test/lib/gem_test.rb
      create  gem_test/lib/gem_test/version.rb
      create  gem_test/gem_test.gemspec
      create  gem_test/Rakefile
      create  gem_test/README.md
      create  gem_test/bin/console
      create  gem_test/bin/setup
      create  gem_test/.travis.yml
      create  gem_test/.rspec
      create  gem_test/spec/spec_helper.rb
      create  gem_test/spec/gem_test_spec.rb
      create  gem_test/LICENSE.txt
      create  gem_test/CODE_OF_CONDUCT.md
Initializing git repo in /Users/Box/Desktop/gem_test/gem_test

何やらゴゴゴッとファイルを生成してくれました。

途中テストファイルについてとか、ライセンスについてとか、コーディング規約についてとか色々聞かれますが、とりあえずYes連打しました。
Gitのリポジトリまで作ってくれるとは気が利いております。

ここからスタート。

まずはコンソールから実行したい

ネットでググったら、どうやらGemの本体は

lib/gem_test.rb

らしい。
とりあえずメソッドを二つサンプルとして作ってみた。

lib/gem_test.rb

require "gem_test/version"

module GemTest
  # Your code goes here...
  def self.hello
    puts "hello!"
  end

  def hello
    "ようこそ"
  end
end

こいつを呼び出してみる。

# irbを起動する
bundle exec irb

# requireする
require "gem_test"

# 呼ぶ
GemTest.hello
"hello!"
=> nil

# さらにincludeする
include GemTest

# 呼ぶ
hello
=> "ようこそ"

ふむふむ。
とりあえず極小だけどGemを作って動かせた。

ビルドする

rake -T コマンドで実行可能なrakeタスクを確認すると。

[ Hakozaru ]% rake -T
rake build            # Build gem_test-0.1.0.gem into the pkg directory
rake clean            # Remove any temporary products
rake clobber          # Remove any generated files
rake install          # Build and install gem_test-0.1.0.gem into system gems
rake install:local    # Build and install gem_test-0.1.0.gem into system gems with...
rake release[remote]  # Create tag v0.1.0 and build and push gem_test-0.1.0.gem to...
rake spec             # Run RSpec code examples

rake build でビルドできそうな匂い。
早速実行してみる。

[ Hakozaru ]% rake build
rake aborted!
WARNING:  See http://guides.rubygems.org/specification-reference/ for help
ERROR:  While executing gem ... (Gem::InvalidSpecificationException)
    "FIXME" or "TODO" is not a description

Tasks: TOP => build
(See full trace by running task with --trace)

なんかTODOを終わらせていないようで怒られました。
探してみると gem_test.gemspec にTODOがあるので、適当に修正して再度ビルドを実行する。

[ Hakozaru ]% rake build
gem_test 0.1.0 built to pkg/gem_test-0.1.0.gem.

今度は成功しました。
pkg/ 以下に lib/gem_test/version.rb で指定されたバージョンも付与されて生成されています。

Gemを使う

生成したGemをRubygemsにアップして使ってもいいし、Githubにpushしてリポジトリ指定して使ってもいいですね。

思ったより簡単に作れて驚きです。
何かいいアイデアが浮かんだら作ってみたいですね!

最後に

"Gem" とは何なのか、完全に理解できたわけではないので、今後も継続的にソース読んだりして勉強したいです。
今はOSSのおかげで教材には困りませんからね!

[続く?]