gemの作り方 ~文字列を返してみるよ~

# gemの作り方
OIC ITCreate Club 第一 Advent Calendar 2017、22日目担当t-kusakabeです。
今回はRubyでgemを作ってみようと思います。

## 環境
ruby:2.4.2を使います。
bundlerをinstallしておいてください。

```
gem install bundler
```

## まずは雛形
gem_sample という名前で作っていくことにします。

```
bundle gem gem_sample -t
```

以下の雛形が出来上がります。

```
.
├── Gemfile
├── README.md
├── Rakefile
├── bin
│   ├── console
│   └── setup
├── gem_sample.gemspec
├── lib
│   ├── gem_sample
│   │   └── version.rb
│   └── gem_sample.rb
└── spec
    ├── gem_sample_spec.rb
    └── spec_helper.rb
```

## gemの説明を追記
gem_sample.gemspecを編集してください。

```

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

Gem::Specification.new do |spec|
  # gemの名前
  spec.name          = "gem_sample"
  spec.version       = GemSample::VERSION
  spec.authors       = ["t-kusakabe"]
  spec.email         = ["アドレス"]

  # 概要を追記
  spec.summary       = %q{OIC ITCreate Club 第一 Advent Calendar 2017}
  # 説明を追記
  spec.description   = %q{gemを作ってみる}
  # homepageを追記
  spec.homepage      = "https://itc.moe/"

  # 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

  spec.files         = `git ls-files -z`.split("\x0").reject do |f|
    f.match(%r{^(test|spec|features)/})
  end
  spec.bindir        = "exe"
  spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
  spec.require_paths = ["lib"]

  spec.add_development_dependency "bundler", "~> 1.16.a"
  spec.add_development_dependency "rake", "~> 10.0"
  spec.add_development_dependency "rspec", "~> 3.0"
end
```

## 実装してみる
ひとまず文字列を返す様にしてみます。

```
require "gem_sample/version"

module GemSample extend self
  def hello
    'Hello OIC ITCreate Club 第一 Advent Calendar 2017'
  end
end
```

helloというメソッドを定義して、 'Hello OIC ITCreate Club 第一 Advent Calendar 2017' という文字列を返します。

## 実行してみる
ちゃんと文字列が返ってくるか確認してみます。

```
bundle
bundle exec irb
require 'gem_sample'
GemSample.hello
=> "Hello OIC ITCreate Club 第一 Advent Calendar 2017"
```

ちゃんと返ってきてくれました！

## buildする

```
gem build gem_sample.gemspec
  Successfully built RubyGem
  Name: gem_sample
  Version: 0.1.0
  File: gem_sample-0.1.0.gem
```

buildが出来るとinstallが出来る様になります。

```
gem install gem_sample

Successfully installed gem_sample-0.1.0
Parsing documentation for gem_sample-0.1.0
Installing ri documentation for gem_sample-0.1.0
Done installing documentation for gem_sample after 0 seconds
1 gem installed
```

## gemを公開してみる
せっかく作ったのでgemを公開してみます。

```
git add .
git commit -m 'init'
```

githubで適当にリポジトリを作成してください。
リポジトリはpublicで作成します。
(今回は 'git@github.com:t-kusakabe/gem_sample.git' を作成しました)

リモートリポジトリを登録します。

```
git remote add origin git@github.com:t-kusakabe/gem_sample.git
git push -u origin master
```

これで作ったgemを公開することができました！
実際に使ってみましょう。

```
cd ~/
mkdir test
cd test
bundle init
```

Gemfileを以下の様に書き換えます。

```
# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem 'gem_sample'
```

編集後installします。

```
bundle 

Fetching gem metadata from https://rubygems.org/.
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Using bundler 1.16.0.pre.3
Using gem_sample 0.1.0
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
```

installできました！

## 最後に。
どうでしたでしょうか。
gemの作成は以外とハードルが低いので汎用性の高いものはgemにしてしまうのもありかもしれません。
個人的な感覚でいうと
複数の処理まとめたい
  -> method化する
複数のmethodをまとめたい
  -> module化する
  -> class化する
他のところでも使いたい
  -> gemにする
みたいな感じで良いかなーと思っています。
ただ最近だとgemをinstallしてからconfigいじったり使うまでに複雑な手順を必要するものもあったりするのでそういうのはgemにするべきではないなーとも思ったりしてます。
興味を持たれた方は是非gemを作ってみてください。