codic」タグアーカイブ

[Ruby] codicAPIを使って英語での命名で楽する

前提

以下のシステム構成で開発、動作確認済み

要素 バージョン
debian 8.6
ruby 2.2.2

成果物

今回開発したツールは以下のリポジトリから取得可能。導入方法はReadme参照
https://github.com/Sa2Knight/codic-ruby

概要

コーディングに特化した翻訳サービスであるcodicのAPIを用いて、Rubyスクリプトから翻訳を行う。翻訳作業をコマンド化し、手軽に利用できるようにする。

codicには各種エディタから利用できるプラグインなどが既にいくつか存在するが、個人的にどれもしっくり来なかったり、機能過剰だったりしたので、自分でAPIを利用して作ってみることにする。

codicについて

codicとは

codicは、プログラマー・システムエンジニアのためのネーミングツール。私含め英語弱者なプログラマは、クラス名、関数名、変数名などの識別子の命名に苦労することが多々ある。

codicはそれをサポートするツールで、日本語で識別子の概要を入力すると、それなりに適した英語に翻訳してくれる。

一見すると、Google翻訳などの機械翻訳と変わらないが、codicはコーディングに特化した翻訳を行い、コード内で頻出する単語に特に力を入れていたり、キャメルケースやスネークケースなどのフォーマットを指定することもできるなど、まさにプログラマ向けの翻訳ツールである

codic APIとは

名の通り、codicのサービスをプログラムから実行するためのAPIである。ユーザ登録こそ必要なものの、OAuth認証などの手続きは必要なく、ユーザ登録時に取得できるアクセストークンをリクエストヘッダに付与するだけで手軽に利用できる。本記事では、日本語を投げると英語が返ってくるEngineAPIのみ利用する。

Engine APIとは

Engine APIは、codicのネーミング生成エンジンにアクセスし、ネーミング変換(和英変換)を行う。

シンプルなリクエストとレスポンスは以下の通り

request(日本語はURLエンコードするものとする)

https://api.codic.jp/v1/engine/translate.json?text=得点を取得する&casing=camel

response

[{"successful"=>true,
  "text"=>"得点を取得する",
  "translated_text"=>"getScore",
  "words"=>
   [{"successful"=>true,
     "text"=>"取得する",
     "translated_text"=>"get",
     "candidates"=>
      [{"text"=>"get"},
       {"text"=>"retrieve"},
       {"text"=>"fetch"},
       {"text"=>"obtain"},
       {"text"=>"acquire"},
       {"text"=>"getting"}]},
    {"successful"=>true,
     "text"=>"得点",
     "translated_text"=>"score",
     "candidates"=>[{"text"=>"score"}, {"text"=>"point"}]},
    {"successful"=>true,
     "text"=>"を",
     "translated_text"=>nil,
     "candidates"=>
      [{"text"=>nil},
       {"text"=>"that"},
       {"text"=>"to"},
       {"text"=>"for"},
       {"text"=>"from"},
       {"text"=>"is"},
       {"text"=>"of"}]}]}]

以上のように、エンジンAPIはGETパラメータで翻訳対象の日本語文字列(text)と、出力フォーマット(casing)を指定するだけで利用できる。

レスポンスは、全体の変換結果及び単語ごとの変換結果、さらに他の変換候補なども返却してくれるが、本記事では単純な変換結果のみ欲しいので、

“translated_text”=>”getScore”

のみ抜き出して利用する。

codic APIの利用準備

codic APIを利用するためには、codic APIのアクセストークンを取得する必要がある。以下の手順で簡単に取得できるので詳細は割愛
1. codicにユーザ登録するする
2. codicにログインし、アカウント設定ページに移動
3. APIをクリックし、以下の画面よりアクセストークンを確認(画像はダミー)

Rubyスクリプトからアクセストークンを利用する必要があるので、実行環境の環境変数にアクセストークンをエクスポートしておく

$ export CODICAPI hogehogehogehgoehgehgheogheohgehog

エクスポートを毎回するのが面倒なので、上記コードをbashrcに追加しておくことをオススメする

Rubyスクリプトの実装

今回は実装内容もシンプルで、OAuthする必要もないため、gemライブラリを利用せず、Rubyの標準モジュールのみで実装を行う。

Codicクラスを作成

スクリプトのベースとなるCodicクラスを以下のように作成する

require 'net/http'
require 'uri'
require 'json'

class Codic
  @@API_URL = "https://api.codic.jp/v1/engine/translate.json"

  def initialize(api_key = nil)
    @api_key = api_key || ENV['CODICAPI']
  end
end
  • APIURLをクラス定数に持たせる
  • アクセストークンを指定してインスタンスを生成する。指定がない場合環境変数を参照する

HTTPリクエストを送信するメソッドを実装

# HTTPリクエストを送信し、レスポンスJSONを戻す
def request(url, params = {})
  uri = URI.parse(appendQueryString(url, params))
  https = Net::HTTP.new(uri.host, uri.port)
  https.use_ssl = true
  req = Net::HTTP::Get.new(uri.request_uri)
  req["Authorization"] = "Bearer #{@api_key}"
  res = https.request(req)
  JSON.parse(res.body)
end
# URLにクエリストリングを付与する
def appendQueryString(url, params = {})
  query_string = params.map {|key, val| "#{key}=#{URI.escape(val)}"}.join("&")
  url += "?#{query_string}" if query_string
  return url
end

requestメソッド

  • Ruby標準モジュールのnet/httpを用いて、HTTPリクエストの作成、送信を行う
  • codicAPIでは、Authorizationヘッダにアクセスキーを付与する必要があるので、インスタンス変数の@api_keyを設定
  • text及びcasingをURLに付与する必要があるので、それはappendQueryStringメソッドに移譲

appendQueryStringメソッド

  • ハッシュ形式のパラメータを、文字列に置き換えてURLに付与する
  • textは日本語が飛んで来るので、URLエンコードを行う

※ どちらもツールの目的から独立したメソッドなのでこのような実装は望ましくない気がするが、軽量ツールなので妥協する

casingをAPI用に変換するメソッドを実装

casingに指定する文字列と出力フォーマットの対応は以下の通り

casing フォーマット 例(データを取得する)
camel キャメルケース getData
pascal パスカルケース GetData
lower underscore 小文字のスネークケース get_data
upper underscore 大文字のスネークケース GET_DATA
hyphen ハイフン刻み get-data
(指定なし) スペース刻み get data

といっても文字列を直接指定するのは面倒なので、アルファベット1文字でそれぞれに変換できる以下のメソッドを実装した

# casingをAPI用に変換する
def convertCasing(casing)
  casingList = {
    'c' => 'camel',
    'p' => 'pascal',
    'l' => 'lower underscore',
    'u' => 'upper underscore',
    'h' => 'hyphen',
  }
  new_casing = casingList[casing]
  new_casing ? new_casing : ''
end
  • c/p/l/u/hをそれぞれの文字列に変換する
  • 該当が無い場合、空文字(指定なし)を返却

翻訳を実行するメソッドを実装

ここまで実装したメソッドを利用して、APIを通して翻訳結果を出力する以下のメソッドを実装した

def translate(text, casing = '')
  casing = convertCasing(casing)
  result = request(@@API_URL, {:text => text, :casing => casing})
  result[0]["translated_text"] if result.class == Array && result[0].include?("translated_text")
end
  • responseは色々返ってくるが、その一部のみしか利用しないのでそこだけ抜き出して返却

エントリポイントの実装

コマンドライン引数を用いてCodicクラスのtranslateメソッドを実行するエントリポイントを実装

codic = Codic.new
word = ARGV[0] || exit
casing = ARGV[1] || ''
puts codic.translate(word, casing)

動作確認

$ ruby codic.rb データを取得
acquisition data
$ ruby codic.rb データを設定 c
settingData
$ ruby codic.rb データを削除 h
deleting-data

シェルスクリプトの実装

これでRubyコマンドを用いた簡易的な翻訳ツールを作成することができた。蛇足かもしれないが、より汎用的に使えるように、このツール自体をコマンド化したい。そこで、シェルスクリプトでcodicコマンドを作成し、それ経由でcodic.rbを呼び出すようにする。

シェルスクリプトの仕様

  • 第一引数に変換する日本語文字列を指定する
  • 第二引数で以下のcasingを指定する(省略可)
    • -c(デフォルト)
    • -p
    • -l
    • -u
    • -h
    • -n
  • Rubyスクリプトを実行し、結果を標準出力

スクリプトパスの定義

先程作成したスクリプトのパスを定義しておく

#!/bin/bash
SCRIPTPATH="/home/vagrant/codicRuby/codic.rb"

ヘルプ関数を作成

よくあるヘルプ関数を以下のように実装する。本関数はコマンド引数が存在しなかった場合に表示する

usage() {
  echo "Codic APIに基いて日本語の翻訳を行う"
  echo "  Usage: codic text [-c] [-p] [-l] [-u] [-h] [-n]"
  echo "オプション:"
  echo "  -c キャメルケースで取得(getData)"
  echo "  -p パスカルケースで取得(GetData)"
  echo "  -l 小文字のスネークケースで取得(get_data)"
  echo "  -u 大文字のスネークケースで取得(GET_DATA)"
  echo "  -h ハイフン刻みで取得(get-data)"
  echo "  -n スペース刻みで取得(get data)"
  exit 1
}

第一引数をチェック

第一引数(翻訳文字列)の存在を確認。存在しない場合前項のヘルプ関数を実行してスクリプトを終了

if [ -n "$1" ]; then
  text=$1
  shift 1
else
  usage
  exit 1
fi

第二引数をチェック

第二引数をチェックし、引数に応じてcasingを設定する

casing="c" #デフォルト設定をここに記述
while getopts cpluhn: OPT
do
  case $OPT in
  c)  casing="c"
      ;;
  p)  casing="p"
      ;;
  l)  casing="l"
      ;;
  u)  casing="u"
      ;;
  h)  casing="h"
      ;;
  n)  casing="n"
      ;;
  esac
done

Rubyスクリプトを実行する

text及びcasingを用いて、Rubyスクリプトを実行する

command="$SCRIPTPATH $text $casing"
ruby $command

コマンドをパスに含める

パスを確認

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

今回は/usr/local/binにハードリンクを作成する

sudo ln codic /usr/local/bin

パスが通っていることを確認

$ which codic
/usr/local/bin/codic

動作確認

text指定なし

$ codic
Codic APIに基いて日本語の翻訳を行う
  Usage: codic text [-c] [-p] [-l] [-u] [-h] [-n]
オプション:
  -c キャメルケースで取得(getData)
  -p パスカルケースで取得(GetData)
  -l 小文字のスネークケースで取得(get_data)
  -u 大文字のスネークケースで取得(GET_DATA)
  -h ハイフン刻みで取得(get-data)
  -n スペース刻みで取得(get data)
$

casing指定なし

$ codic データを取得する
getData

casing指定あり

$ codic データを設定する -u
SET_DATA

所感

  • 今までで一番手軽に利用できるAPIだったので使っていて楽しかった
  • 英語弱者なので命名が苦手だったので使えそう(あくまで参考程度に)
  • Vim上で効率的に利用したいので、これを元にvimプラグインを作ってみたい