Ruby gemを公開した

# 概要
とあるRailsアプリに急遽とあるライブラリが必要となりました。
関連するgemをgithubで検索したりぐぐってもヒットしないため、自作することにしました。

ソースコード・ライブラリはgithubやrubygemsに公開しています。

# 開発したgem: niwa_textream
https://github.com/niwatolli3/niwa_textream

Yahoo! Textreamをスクレイピングするgemを開発しました。
ミーハーなので、Selenium等で流行りのPage Object Patternを適用してみました。

* 言語:ruby
* テスト:RSpec
* CI:Travis CI
* コーディングルールチェック:Rubocop

```
$ bundle gem niwa_textream -t #gem(niwa_textream)の雛形を作る
$ vim niwa_textream/niwa_textream.gemspec # gemspecを編集する。TODOを書き換える。
```
```ruby:niwa_textream.gemspec
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'niwa_textream/version'

Gem::Specification.new do |spec|
  spec.name          = "niwa_textream" # ライブラリ名を書き換える
  spec.version       = NiwaTextream::VERSION
  spec.authors       = ["niwatolli3"] # authorsを書き換える
  spec.email         = ["niwatolli3@gmail.com"] # 自分のメアドに変える

  spec.summary       = %q{A scraping library for Yahoo! Textream} #summaryを書く
  spec.description   = %q{NiwaTextream provides scraping feature for Yahoo! Textream.} # descriptionを書く
  spec.homepage      = "https://github.com/niwatolli3/niwa_textream" #urlを記述。今回はgithubにソースを公開したため、githubのurlを記述
  spec.license       = "MIT" # ライセンスを記述

  # 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'] = "https://rubygems.org" # rubygems.orgにpushできるようにするため
  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 { |f| f.match(%r{^(test|spec|features)/}) }
  spec.bindir        = "exe"
  spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
  spec.require_paths = ["lib"]

  spec.add_development_dependency "bundler", "~> 1.12"
  spec.add_development_dependency "rake", "~> 10.0"

  # for test
  spec.add_development_dependency "rspec" # rspecを使うため追記

  spec.add_development_dependency "codeclimate-test-reporter" # 追記

  # for this gem
  spec.add_dependency "nokogiri" # 依存するライブラリを追記
  spec.add_dependency "mechanize" # 依存するライブラリを追記
end
```

Gemを実装する

```ruby:lib/niwa_textream.rb
require "niwa_textream/version"
require "mechanize"

%w[ models/category pages/top/top_page pages/category/category_page ].each do |file|
  require "niwa_textream/#{ file }"
end

module NiwaTextream
end
```

今回は1つのPageを実装する度にテストコードを追加したうえでgithubにpushしました。
githubにpushされるとTravis CIにフックがかかり、リグレッションテストが実行されるようにしました。
CIを回すことでデグレを防ぎ、また効率よく開発することができました。

テストコードの一例

```ruby:spec/pages/thread_page/thread_page.rb
require "niwa_textream/pages/top/top_page"

describe 'ThreadPage' do
  before :all do
    mecha = Mechanize.new
    NiwaTextream::TopPage.goTo(mecha)
    @topPage = NiwaTextream::TopPage.new(mecha)
    cat_name = '野球実況'
    @categoryPage = @topPage.clickCategory(cat_name)
    @threadPage = @categoryPage.clickCategory('副音声')
    @threads = @threadPage.threads
  end

  describe 'thread' do
    it 'have more than 1 threads' do
      expect(@threads.count).to be >= 1
    end

    it 'have title (not empty' do
      expect(@threads[0].title).not_to be ""
    end

    it 'have more than 1 comment' do
      expect(@threads[0].num_comment).to be >= 1
    end

    it 'have last updated time (DateTime)' do
      expect(@threads[0].last_updated).to be_kind_of(DateTime)
    end

    it 'have elem' do
      expect(@threads[0].elem).not_to be nil
    end

    it 'have no prev page link' do
      expect(@threadPage.prev_page_elem).to be_nil
    end

    it 'have next page link' do
      expect(@threadPage.next_page_elem).not_to be_nil
    end

    it 'can go to next page and prev page link will appear' do
      @threadPage = @threadPage.clickNextPage
      # the prev link will appear
      expect(@threadPage.prev_page_elem).not_to be_nil
      # the next link will appear
      expect(@threadPage.next_page_elem).not_to be_nil
      @threadPage = @threadPage.clickPrevPage
    end

    it "can go to next page and the first post's date is older than the 1st page's last post" do
      first_last_post = @threads.last
      @threadPage = @threadPage.clickNextPage
      next_first_post = @threadPage.threads.first
      expect(next_first_post.last_updated).to be <= first_last_post.last_updated
    end
  end
end
```

## rubygems.orgにpush する
```
$ git add . -A
$ git commit -m "hi"
$ rake build # gemファイルを生成する
$ curl -u [username] https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials # credentialを保存する
$ gem push niwa_textream-0.1.0.gem
```

オフィシャルのドキュメントによれば、数分で公開されるようです。
https://rubygems.org/gems/niwa_textream

公開されました。めでたしめでたし。