Ruboty | 各種 Generator を利用して Ruboty のプロダクトコード・README・Qiita記事の作成コストを下げる #ruboty

# Ruboty | 各種 Generator を利用して Ruboty のプロダクトコード・README・Qiita記事の作成コストを下げる #ruboty

## <i class="fa fa-cubes" style="font-size:1em;"></i> 概要
Generator を利用して Ruboty のプロダクトコード・テストコード・README・Qiita記事の作成コストを下げます

## <i class="fa fa-cube" style="font-size:1em;"></i> 前提知識
<i class="fa fa-external-link" style="font-size:1em;"></i>  [Ruboty | 基本構成図解](http://qiita.com/tbpgr/items/7f08569dd8828bae6527)
<i class="fa fa-external-link" style="font-size:1em;"></i>  [Ruboty | Handlers と Actions](http://qiita.com/tbpgr/items/9b416529df6ce212b86d)

普段 Actions を作成しない構成で Ruboty Handler Plugin を作成している方は
上記の記事で構成を把握してから読み進めてください。

## <i class="fa fa-cube" style="font-size:1em;"></i> 使用する Generator 
### ruboty-gen ( author: @blockgiven さん )
<a href="https://github.com/blockgiven/ruboty-gen" target="_blank" title="ruboty-genを開く"><i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [ruboty-gen GitHub](https://github.com/blockgiven/ruboty-gen)

#### 自動生成範囲

* プロジェクトのひな形 ( bundle gem your_plugin_name と同等 )
* プロダクトコードのひな形（モジュール、クラス、メソッド宣言）
* gemspec のひな形

### ruboty-megen ( author: tbpgr ※私 )
<a href="https://github.com/tbpgr/ruboty-megen" target="_blank" title="ruboty-megenを開く"><i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [ruboty-megen GitHub](https://github.com/tbpgr/ruboty-megen)
#### 自動生成範囲
README.md

### ruboty-articlegen ( author: tbpgr ※私 )
<a href="https://github.com/tbpgr/ruboty-articlegen" target="_blank" title="ruboty-articlegenを開く"><i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [ruboty-articlegen GitHub](https://github.com/tbpgr/ruboty-articlegen)
#### 自動生成範囲
Qiita のエントリのテンプレート

## <i class="fa fa-cube" style="font-size:1em;"></i> 試行
### <i class="fa fa-files-o" style="font-size:1em;"></i> 仕様
FizzBuzz Plugin を作ります

### ruboty-articlegen で記事のテンプレートを作成
仕様を明確にするため、 Qiita の記事のひな形をはじめに作成します。

* Qiita 記事作成用の 内部 DSL 形式の設定ファイルを生成します

~~~bash
$ ruboty-articlegen init
$ ls -F
Rubotyariticle
~~~

* Rubotyariticle を編集

~~~ruby
# encoding: utf-8
user_name "tbpgr"
gem_name "fizzbuzz"

title "FizzBuzz の機能を持つ ruboty-fizzbuzz を作成しました"
purpose <<-PURPOSE
自動生成ツールの説明のためのプロジェクトなので、サンプルプログラムの定番 FizzBuzz を採用しました。
3 の倍数の時に Fizz
5 の倍数の時に Buzz
15 の倍数の時に FizzBuzz
その他の時に 数値をそのまま
出力します
PURPOSE

env do |e|
  e.name "--"
  e.description "--"
end

dependency do |d|
  d.name "--"
  d.description "--"
end

command do |c|
  c.name "fizzbuzz"
  c.pattern "/fizzbuzz (?<number>.*?)\z/"
  c.description "Output FizzBuzz result"
  c.example <<-EXAMPLE
>ruboty fizzbuzz 3
>Fizz
>ruboty fizzbuzz 5
>Buzz
>ruboty fizzbuzz 15
>FizzBuzz
>ruboty fizzbuzz 2
>2
  EXAMPLE
end
~~~

* Qiita の記事のひな形を生成します

~~~bash
$ ruboty-articlegen generate
$ ls -F
Rubotyariticle  ruboty-fizzbuzz.md
~~~

* 生成された Markdown ( ruboty-fizzbuzz.md )

※下記よりプレビューを確認可能  
<a href="https://github.com/tbpgr/ruboty-fizzbuzz/blob/master/article_samples/ruboty-fizzbuzz.md" target="_blank" title="ruboty-fizzbuzz.mdを開く"><i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [生成された Qiita記事用 Markdown のひな形](https://github.com/tbpgr/ruboty-fizzbuzz/blob/master/article_samples/ruboty-fizzbuzz.md)

### ruboty-megen で README.md のテンプレートを作成
Qiita の記事とほぼ同じ内容だったりします。

* README.md 作成用の 内部 DSL 形式の設定ファイルを生成します

~~~bash
$ ruboty-megen init
$ ls -F
Rubotyme
~~~

* Rubotyme を編集

~~~ruby
# encoding: utf-8
user_name "tbpgr"
gem_class_name "Fizzbuzz"
gem_name "fizzbuzz"

title "output fizzbuzz result"
command do |c|
  c.name "fizzbuzz"
  c.pattern "/fizzbuzz (?<number>.*?)\z/"
  c.description "Output FizzBuzz result"
end
~~~

* README.md のひな形を生成します

~~~bash
$ ruboty-megen generate
$ ls -F
Rubotyariticle  ruboty-fizzbuzz.md
~~~

* 生成された Markdown ( README.md )

※下記よりプレビューを確認可能  
<a href="https://github.com/tbpgr/ruboty-fizzbuzz/blob/master/readme_samples/README1.md" target="_blank" title="README1.mdを開く"><i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [生成された README.md のひな形](https://github.com/tbpgr/ruboty-fizzbuzz/blob/master/readme_samples/README1.md)

### ruboty-gen で Plugin のテンプレートを作成

~~~bash
# 最初の fizzbuzz は gem 名。 次の fizzbuzz はアクション名（複数アクションある場合は複数指定可）
$ ruboty-gen gem fizzbuzz fizzbuzz
$ tree
┠ README.md
┠ Rubotyariticle
┠ ruboty-fizzbuzz
┃ ┠ Gemfile
┃ ┠ lib
┃ ┃ ┗ ruboty
┃ ┃     ┠ fizzbuzz
┃ ┃     ┃ ┠ actions
┃ ┃     ┃ ┃ ┗ fizzbuzz.rb
┃ ┃     ┃ ┗ version.rb
┃ ┃     ┠ fizzbuzz.rb
┃ ┃     ┗ handlers
┃ ┃         ┗ fizzbuzz.rb
┃ ┠ LICENSE.txt
┃ ┠ Rakefile
┃ ┠ README.md
┃ ┗ ruboty-fizzbuzz.gemspec
┠ ruboty-fizzbuzz.md
┗ Rubotyme
~~~

### Plugin を実装
※今回はテストを作成しません

* lib/ruboty/handlers/fizzbuzz.rb  
自動生成された Handler のひな形に実装を追加します。
変更が必要なのは on の各引数のみです。

~~~ruby
require "ruboty/fizzbuzz/actions/fizzbuzz"

module Ruboty
  module Handlers
    class Fizzbuzz < Base
      # 編集が必要なのはこの行のみ
      on /fizzbuzz (?<number>.*?)\z/, name: 'fizzbuzz', description: 'output fizzbuzz result'

      def fizzbuzz(message)
        Ruboty::Fizzbuzz::Actions::Fizzbuzz.new(message).call
      end
    end
  end
end
~~~

* lib/ruboty/fizzbuzz/actions/fizzbuzz.rb  
Action の自動生成コードは、module 宣言・ class 宣言 ・ call メソッドの宣言部のみ。
残りの実処理を実装します。

~~~ruby
module Ruboty
  module Fizzbuzz
    module Actions
      class Fizzbuzz < Ruboty::Actions::Base
        def call
          message.reply(fizzbuzz)
        end

        private

        def fizzbuzz
          case message[:number]
          when fizzbuzz? then "FizzBuzz"
          when buzz? then "Buzz"
          when fizz? then "Fizz"
          else message[:number]
          end
        end

        def fizzbuzz?; ->(v){v % 15 == 0}; end
        def buzz?; ->(v){v % 5 == 0}; end
        def fizz?; ->(v){v % 3 == 0}; end
      end
    end
  end
end
~~~

### README.md を仕上げる
* 予め ruboty-megen で自動生成しておいてた内容に置き換えます
* Usage の内容を記述します

<a href="https://github.com/tbpgr/ruboty-fizzbuzz/blob/master/readme_samples/README2.md" target="_blank" title="README2.mdを開く"><i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [編集後の README.md](https://github.com/tbpgr/ruboty-fizzbuzz/blob/master/readme_samples/README2.md)

### gemspec を仕上げる
下記の項目を設定します。

* spec.summary
* spec.description
* spec.homepage

~~~ruby
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'ruboty/fizzbuzz/version'

Gem::Specification.new do |spec|
  spec.name          = "ruboty-fizzbuzz"
  spec.version       = Ruboty::Fizzbuzz::VERSION
  spec.authors       = ["tbpgr"]
  spec.email         = ["tbpgr@tbpgr.jp"]
  spec.summary       = %q{An Ruboty Handler + Actions to output fizzbuzz result.}
  spec.description   = %q{An Ruboty Handler + Actions to output fizzbuzz result.}
  spec.homepage      = "https://github.com/tbpgr/ruboty-fizzbuzz"
  spec.license       = "MIT"

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

  spec.add_runtime_dependency "ruboty"
  spec.add_development_dependency "bundler", "~> 1.7"
  spec.add_development_dependency "rake", "~> 10.0"
end
~~~

### gem を RubyGems 公開します ※実際には公開していません

~~~bash
$ rake release
~~~

### shell adapter で動作確認

* Gemfile

~~~ruby
source "https://rubygems.org"

gem "ruboty"
gem 'ruboty-fizzbuzz'
~~~

* 実行

~~~bash
$ bundle exec ruboty
> ruboty /fizzbuzz (?<number>.*?)\z/         - output fizzbuzz result
> ruboty fizzbuzz 15
FizzBuzz
> ruboty fizzbuzz 5
Buzz
> ruboty fizzbuzz 3
Fizz
> ruboty fizzbuzz 1
1
~~~

### Qiita の記事 を公開します
※特に変更の必要がなければ下記のひな形のままで良い

<a href="https://github.com/tbpgr/ruboty-fizzbuzz/blob/master/article_samples/ruboty-fizzbuzz.md" target="_blank" title="ruboty-fizzbuzz.mdを開く"><i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [生成された Qiita記事用 Markdown のひな形](https://github.com/tbpgr/ruboty-fizzbuzz/blob/master/article_samples/ruboty-fizzbuzz.md)

### まとめ
以上で

* Ruboty Handler Plugin の実装
* Ruboty Handler Plugin のリリース
* Qiita の公開エントリ

が完了しました。

Ruboty Handler Plugin の実装のために必要になる共通の宣言部や、
README のひな形を毎回記述する必要がなくなりました。

Qiita の投稿とワンセットで Ruboty Handler Plugin を作成する場合は、
記事の作成の手間も大幅に省けました。

実際に上記の手順で作成した ruboty-fizzbuzz は GitHub に公開してあります。
<a href="https://github.com/tbpgr/ruboty-fizzbuzz" target="_blank" title="ruboty-fizzbuzzを開く"><i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [ruboty-fizzbuzz GitHub](https://github.com/tbpgr/ruboty-fizzbuzz)

## <i class="fa fa-arrow-circle-right" style="font-size:1em;"></i> 参照
<i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [ruboty GitHub](https://github.com/r7kamura/ruboty)
<i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [ruboty-gen GitHub](https://github.com/blockgiven/ruboty-gen)
<i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [ruboty-megen GitHub](https://github.com/tbpgr/ruboty-megen)
<i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [ruboty-articlegen GitHub](https://github.com/tbpgr/ruboty-articlegen)
<i class="fa fa-github-square" style="color: black;font-size:1em"></i></a> / [ruboty-fizzbuzz GitHub](https://github.com/tbpgr/ruboty-fizzbuzz)