【Ruby】RubyGemsの作り方 - freee-apiを作るまで -

## はじめに

皆さん、こんにちは。ここ最近の私の主業ですが会社での仕事を通じて、Rubyプログラムをゴリゴリ書いていました。直近2ヶ月で作成したRubyプログラムですが、こちらを皆様にも利用できるように、RubyGemsでリリースする事としました。今回は、RubyGemsへRubyプログラムをリリースするまでの知見を共有したいと思います。

## 公開したGems

今回リリースしたgemsはこちらになります。

[https://rubygems.org/gems/freee-api](https://rubygems.org/gems/freee-api)

当社では会社で掛かった会計を、[クラウド会計ソフトfreee](https://www.freee.co.jp/) に登録する動きとなりました。今回はRailsアプリに会計登録機能を実現するため、freeeの機能を外部プログラムから実行できるようにAPIを利用する必要が出てきました。
freee APIについてはこちら

[https://support.freee.co.jp/hc/ja/articles/115000143186-freee-API%E3%81%A8%E3%81%AF](https://support.freee.co.jp/hc/ja/articles/115000143186-freee-API%E3%81%A8%E3%81%AF)

freee側では、APIを提供しているのみでRubyプログラムから別途APIを叩けるような機構が存在しません。
そこで、私の方ではRubyプログラムからfreee APIを実行できるラッパーを作成する事としました。それが、今回のGemsとなります。
次からは実際にリリースするまでの手順や知見を共有したいと思います。

## gem作成準備

リリースに必要な手順を調べるために参考にした文献がこちらとなります。

1. [RubyGemsの作り方](https://qiita.com/chamao/items/9813e18d82b51c99422c)
2. [作ったgemをリリースするまで](https://qiita.com/kyohei8/items/b292f727e213ed7db9d7)

### 雛形の作成

まずはfreee-apiの雛形の作成を行います。事前にディレクトリを作成する必要はありませんが、rbenvでインストールしているrubyを指定したかったので、あらかじめ利用するrubyのversionを指定してから始めています。

```bash
$ rbenv local 2.3.6
$ bundle exec freee-api
```

gemの初回作成時には以下のことを対話形式で聞かれます。

```bash
Creating gem 'freee-api'...
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 https://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 https://bit.ly/coc-enforcement. y/(n): y
```

### freee-api.gemspecの修正

雛形で作成したgemspecファイルの中に `TODO` のワードが含まれていると、bundleできないため、以下の三つを書き直します。

```ruby:freee-api.gemspec
  spec.summary       = 'Freee Api'
  spec.description   = 'Wrapper of freee api. This gem using of wrapper via OAuth2.'
  spec.homepage      = 'https://github.com/himrock922/freee-api.git'
```

以上最低限の設定を行い、後はコードをガリガリ書いていきます。

## リリース前の修正・テスト

コードを書き終えいよいよリリースという所ですが、リリース前にある程度Gemが正しく動くか、また今後のメンテナンスを容易にするために、RuboCopによるコード修正とRspecのテスト駆動を追加しました。
以下の操作を実行するために、追加のgemが必要となります。しかし、このgemをインストールするために必要なgemという訳ではなく、あくまで開発用に必要なgemという事なので、あらかじめ.gemspecファイルで開発用に必要なgemをまとめています。

```ruby:freee-api.gemspec
  spec.add_development_dependency 'bundler', '~> 1.16'
  spec.add_development_dependency 'rake', '~> 10.0'
  spec.add_development_dependency 'rspec', '~> 3.0'
  spec.add_development_dependency 'pry-byebug', '~> 3.6.0'
  spec.add_development_dependency 'rubocop', '~> 0.58.1'
  spec.add_development_dependency 'yard', '~> 0.9.15'
  spec.add_development_dependency 'webmock', '~> 3.4.2'
```

因みにgemインストールに必要な関連gemは`add_dependecy` で追加しています。

```ruby:freee-api.gemspec
  spec.add_dependency 'oauth2', '~> 1.4.0'
  spec.add_dependency 'faraday', '~> 0.12.2'
  spec.add_dependency 'faraday_middleware', '~> 0.12.2'
```

### RuboCop

```yaml:.rubocop.yml
AllCops:
  TargetRubyVersion: 2.3
  DisplayCopNames: true
  DisplayStyleGuide: true
  Exclude:
    - bin/*
    - vendor/**/*

Bundler/OrderedGems:
  Enabled: false

CyclomaticComplexity:
  Max: 7

Gemspec/OrderedDependencies:
  Enabled: false

Rails:
  Enabled: false

Style/Documentation:
  Enabled: false

# allow Japanese comments
AsciiComments:
  Enabled: false

# パラメータ列挙等もあるので行数・列幅は多少緩和する
LineLength:
  Max: 180

ClassLength:
  Max: 200

ModuleLength:
  Max: 200

MethodLength:
  Max: 50

BlockLength:
  Max: 50
  Exclude:
    - Rakefile
    - '**/*.rake'
    - 'spec/**/*.rb'

# 概念上明らかなドキュメントは省略可能
Documentation:
  Enabled: false

FileName:
  Exclude:
    - Capfile

# ABC Sizeの基準値の緩和
Metrics/AbcSize:
  Max: 40
```

作成したコードをGithubにpushする前に、rubocopによってある程度、インデント整理やコード修正を行います。

```bash
% bundle exec rubocop -a                                             (git)-[master]
Inspecting 19 files
...................

19 files inspected, no offenses detected
```

### Rspec

gemのメソッドが正しく実行できているかどうか、考えられるシナリオを網羅して想定する結果が出るかどうか判断するためにRspecによるテストコードを書きます。
ローカルでもテスト実行ができるのですが、公開する際に最低限Specテストがクリアしているかどうか確認できるように、CIによるテスト駆動が行えるようにしました。
今回、利用したCIサービスは `TravisCI`です。
TravisCIはOSSであれば、[無料でCIのサービスを利用する事ができるため](https://travis-ci.org/)
、公開用のチェックとしてTravisCIを採用しました。

リポジトリに.travis.ymlを追加する事で自動的にCIが動くようになります。

```yaml:.travis.yml
sudo: false
language: ruby
rvm:
  - 2.3.6
before_install: gem install bundler -v 1.16.1
install: bundle install --deployment
cache:
  directories: vendor/bundle
```

また、CIによるRSpecのテストがちゃんと全部クリアしたかどうか一眼でわかるようにREADMEに以下のリンクを追加します。

```README
[![Build Status](https://travis-ci.org/himrock922/freee-api.svg?branch=master)](https://travis-ci.org/himrock922/freee-api)
```

これにより、READMEを確認する事でテストが通っているかどうかチェックすることができます。

![スクリーンショット 2018-08-26 03.53.23.png](https://qiita-image-store.s3.amazonaws.com/0/144991/f3f153cb-62b1-5ac1-1965-8352cddf819e.png)

## リリース

全ての準備が終わり次第、リリースしていきます。

rubygems.orgのアカウントを登録しAPIアクセス用の鍵を作成する事でrubygems.orgへのリリース操作を実行する事ができます。

```bash
curl -u rubygems_account_name https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
```

PRやらpushやらでコードを変更し、versionも変更した後はリリースをするだけです。

```
% bundle exec rake release
```

## Freee-APIについて

今回は会社での仕事を通じてgemをリリースする際のノウハウを執筆しました。
一応、当社の仕事で必要な機能は実現できているため仕事としてのgem開発は一旦終了です。
とはいえ、提供されている全てのインタフェースを網羅できているわけではないため、プライベートで徐々に作っていくフローになるかと思われます。

issueであげていただければ優先的に対応しますし、何より僕のモチベーションも上がるため、開発に協力していただける方は是非一度ご利用してみてください。

それでは今回作成したfreee-apiのリポジトリを最後にリンクとして張っておきます。


[https://github.com/himrock922/freee-api](https://github.com/himrock922/freee-api)