ダミーデータ生成CLIツール fakes-gen

# fakes-gen
年内に自作のダミーデータ作成CLIツールのfakes-genがアップデートできたので、記事にまとめてみました。
[github](https://github.com/ogata-k/fakes-gen-cli/tree/master)だけでなく[crates.io](https://crates.io/crates/fakes-gen)にもあります。
皆さんに使ってほしいので、この記事では[README.md](https://github.com/ogata-k/fakes-gen-cli/blob/master/README.md)を元に詳しくfakes-genの解説をしていく予定です。2019/12/31現在のバージョンは0.2.2です。


# できること
fakes-genは雑に言うとライブラリ及びCLIツールとしても利用可能な高機能fakerです。以下のことができます。
## ライブラリとして
* 多言語拡張容易性があります。fakerの実態は乱択ですので、ライブラリで利用している使用するデータセットを変えるだけで実現可能です。
* 名前の漢字とフリガナを統一させることができます。レコード内で名前が出てきたらその名前情報を一括で取得しておいて保持しておくことで、「山田 太郎」というデータには「ヤマダ タロウ」というデータが生成できるようになっています。
* ほかのダミーデータと組み合わせたダミーデータが生成できます。例えばアカウント名用に使える文字列を生成するオプションと固定文字の@をつなげて「@user_name」というのも生成可能です。残念ながら組み合わせたデータに対しては上記のフリガナ対応はしていません。
* 固定値を生成できます。例えば利用中を表すデータとして1という固定値で欲しい、という場合に場合に常に1を返すことができます。
* 指定範囲から乱択をすることができます。例えば利用状況を表すデータとして利用中の1、一時利用中の3、利用停止中の5, 削除の9といった状況で、[1,3,5,9]のようなリストから乱択でデータを取ってくるような使い方ができます。
* 日時のダミーデータは必ず過去の時間を生成するようになっています。というのもアカウント作成日とか更新日とかは未来の値をとることはないからです。
* 時間のフォーマットを指定できます。せっかく日時を取得するのに使っているクレート[Chrono](https://crates.io/crates/chrono)にフォーマット機能があるので指定できるようになっています。フォーマットについては[chronoの指定可能フォーマット一覧](https://docs.rs/chrono/0.4.9/chrono/format/strftime/index.html#specifiers)を参照してください。

## CLIツールとして
上記のライブラリとして以外に次のことが可能です。
* csvやjsonのフォーマット変換が可能です。データベースやCSVアップロードのためにCSVファイルが欲しい場合や取得データの表現としてjson形式のデータが欲しい場合に対応できます。
* レコード数の調節ができます。CLIツールで時々1レコード分しか出力してくれないみたいなことがありますが、fakes-genではレコード数を指定できます。
* ヘッダの有無を切り替えることができます。データの最初からだからヘッダが欲しい、や途中からだからヘッダはいらないといった状況に対処が可能です。ただ、json対応の都合上ヘッダを使わない場合でもヘッダ名は必須になっています。
* ライブラリの時と違い組み合わせオプションのネストはできません。ご注意ください。

# インストール
ライブラリとしては

```
// Cargo.toml
fakes-gen = "version"
```

CLIツールとしては

```
cargo install --git https://github.com/ogata-k/fakes-gen-cli --branch master
```
や

```
cargo install fakes-gen
```
でインストールできます。

# CLIツールの使い方
まずヘルプを``` fakes-gen -h ```でヘルプを見てみます。

```
fakes-gen 0.2.2
ogata-k <ogtkzk712@gmail.com>
This CLI tool is generate dummys whose option you specified.
You can also specify formatter for csv, tsv and json.
This program support multi-locale. When not support your locale and you want your locale faker, please pull-request your
locale dummy data at https://github.com/ogata-k/fakes-gen-cli/pulls.

USAGE:
    fakes-gen [FLAGS] [OPTIONS] [option]...

FLAGS:
    -b, --bnf         show Backus-Naur Form and detail format for options
    -f, --fullform    flag for generating as fullform such as body with header
    -h, --help        Print this message
    -u, --usable      show list of all usable options for faker
    -V, --version     Prints version information

OPTIONS:
    -c, --converter <converter>    converter for output [default: csv]  [possible values: csv, tsv, json]
    -l, --locale <locale>          3-char's country code. [default: jpn]  [possible values: jpn]
    -s, --size <size>              data size. If 1, generate as record. If over 1, generate as data_set. [default: 1]

ARGS:
    <option>...    options with name of column for faker

```
メッセージを読めば先ほどの説明から大体は何ができるかはわかると思います。そのため先の説明ではわからない```-b```と```-u```フラグ、```option```指定について説明します。

## ```-b```フラグ
まずは```-b```フラグです。```fakes-gen -b```と入力して実行すると次のようなメッセージが出てきます。

```
All Backus-Naur Form for Option(<option>)
<option> := <normal_option>|<special_option>
<normal_option> := <category>\.<option_name>\(<column_name>(#<sub_option>)?\)
<special_option> := <with_join_option>
<with_join_option> := With\.Join\(<column_name>#<join_separator>(#<repeatable_option>)*\)
<join_separator> := [^#]*
<repeatable_option> := <unsigned_integer>?#<option_without_column_name>
<option_without_column_name> := <category>\.<option_name>\((<sub_option>)?\)
<category> := [A-Z][0-9a-zA-Z]*
<option_name> := [A-Z][0-9a-zA-Z]*
<column_name> := <string>
<sub_option> := <string>|<string_list>|<unsigned_integer_range>|<signed_integer_range>|<boolean>|<format_string>
<string> := ((".*")|[.[^\ ]]*)
<string_list> := \[<string>(#<string>)*\]
<unsigned_integer_range> := <unsigned_integer>#<unsigned_integer>
<signed_integer_range> := -?<unsigned_integer>#-?<unsigned_integer>
<unsigned_integer> := [0-9][1-9]*
<bool> := (true)|(false)
<format_string> := <string>
If you want to know <format_string>, please reference to https://docs.rs/chrono/0.4.9/chrono/format/strftime/index.html#specifiers
```
一行目からわかるように```option```引数のフォーマットのBNFによる説明の一覧です。```option```引数の構文解析で受理してくれる構文ということになります。
例えば``` Hoge.Fuga("column_name"#sub-option) ```みたいなのが構文としては有効となります。

## ```-u```フラグ
次に```-u```フラグです。```fakes-gen -u```と入力すると次のようなメッセージが出てきます。

```
Category:
 With
Options:
・With\.Join\(<column_name>#<join_separator>(#<repeatable_option>)*\)

Category:
 Fixed
Options:
・Fixed.String\(<column_name>#<string>\)
・Fixed.NotString\(<column_name>#<string>\)

Category:
 Select
Options:
・Select.String\(<column_name>#<string_list>\)
・Select.NotString\(<column_name>#<string_list>\)

Category:
 Lorem
Options:
・Lorem.Word\(<column_name>(#<unsigned_integer_range>)?\)
・Lorem.Sentence\(<column_name>(#<unsigned_integer_range>)?\)
・Lorem.Paragraph\(<column_name>(#<unsigned_integer_range>)?\)

Category:
 Name
Options:
・Name.FirstName\(<column_name>\)
・Name.FirstNameFurigana\(<column_name>\)
・Name.LastName\(<column_name>\)
・Name.LastNameFurigana\(<column_name>\)
・Name.FullName\(<column_name>\)
・Name.FullNameFurigana\(<column_name>\)

Category:
 Primitive
Options:
・Primitive.Int\(<column_name>(#<signed_integer_range>)?\)
・Primitive.Float\(<column_name>(#<signed_integer_range>)?\)
・Primitive.Ascii\(<column_name>(#<signed_integer_range>)?\)
・Primitive.Bool\(<column_name>\)

Category:
 Internet
Options:
・Internet.Email\(<column_name>\)
・Internet.UserName\(<column_name>\)
・Internet.Password\(<column_name>#<unsigned_integer_range>\)
・Internet.CreditCard\(<column_name>\)
・Internet.URL\(<column_name>\)
・Internet.IPv4\(<column_name>\)
・Internet.IPv6\(<column_name>\)
・Internet.RGB\(<column_name>\)
・Internet.RGBA\(<column_name>\)
・Internet.UserAgent\(<column_name>\)
・Internet.StatusCode\(<column_name>\)

Category:
 Company
Options:
・Company.Suffix\(<column_name>\)
・Company.Name\(<column_name>\)
・Company.Industry\(<column_name>\)

Category:
 Address
Options:
・Address.Building\(<column_name>\)
・Address.Street\(<column_name>\)
・Address.City\(<column_name>\)
・Address.State\(<column_name>\)
・Address.CountryCode\(<column_name>\)
・Address.CountryName\(<column_name>\)
・Address.TimeZone\(<column_name>\)
・Address.Address\(<column_name>\)
・Address.ZipCode\(<column_name>(#<bool>)?\)
・Address.Phone\(<column_name>(#<bool>)?\)
・Address.Latitude\(<column_name>\)
・Address.Longitude\(<column_name>\)

Category:
 DateTime
Options:
・DateTime.Time\(<column_name>#<format_string>\)
・DateTime.Date\(<column_name>#<format_string>\)
・DateTime.DateTime\(<column_name>#<format_string>\)

Category:
 FileSystem
Options:
・FileSystem.FileName\(<column_name>\)
・FileSystem.Extension\(<column_name>\)
```
利用可能な```option```引数一覧ですね。```option```引数の意味解析で受理するトークン列の一覧のようなものです。
組み合わせからダミー語、名前、インターネット情報、住所、日時やファイルなどいろいろなオプションが使用可能です。
今後UTF8テキストや連番オプションなど増えていく予定です。

# 使用例
```
fakes-gen With.Join(_#_dd_#Select.String(hoge#sss)#2#Select.NotString(1#2#3))  // "sss_dd_1_dd_2"
fakes-gen Fixed.String(_#hoge)  // "hoge"
fakes-gen Select.NotString(_#hoge#fuga)  // hoge
fakes-gen Lorem.Word(_)  // "氷山"
fakes-gen Lorem.Word(_#2#4)  // "有向グラフ Haskell Rust" 
fakes-gen Name.FullName(_) Name.LastNameFurigana(_) Name.FirstNameFurigana(_)  // "露木 静男","ツユキ","シズオ"
fakes-gen Primitive.Float(_)  // -32544.35
fakes-gen Primitive.Float(_#-1#1)  // -0.87
fakes-gen Internet.URL(_) Internet.StatusCode(_)  // "http://example.com/B/lUVB","6IxT4VL92u"
fakes-gen Company.Name(_) Company.Industry(_)  // "フリーダム匿名組合","宿泊業"
fakes-gen Address.Phone(_#true)  // "03-357-1407"
fakes-gen DateTime.Date(_#%m/%d) DateTime.Time(_)  // "08/17","18:06:18"
fakes-gen FileSystem.FileName(_)  // "8yIY6C4Pl.csv"
fakes-gen -- FileSystem.FileName(_)  // "2pkr0Fs1W8xC.ras"

fakes-gen -f FileSystem.FileName(_) 
// "_"
// "3YDnf5h0WzVJ.url"

fakes-gen -c json FileSystem.FileName(_)
// {
//   "_": "rcYWtp.art"
// }

fakes-gen -s 2 -c json FileSystem.FileName(_)
// [
//   {
//     "_": "Xt6n8VFOPIbT.ra"
//    },
//    {
//      "_": "1ov76VYjG.jar"
//    }
//  ]

fakes-gen -s 2 -f -c json FileSystem.FileName(_)
// {
//   "dummy": [
//     {
//       "_": "ZWYih0WFAB.tmp"
//     },
//     {
//       "_": "8IiUSgNhtCson3.mpg"
//     }
//   ]
// }
```

# まとめ
以上自作のライブラリ兼CLIツールのfakerのfakes-genの詳解でした。個人的には業務でも開発ツールとして使えるようなものになったと思っています。（実際私が使っているので。）皆さんもよいなと思ったら使ってあげてください。よろしくお願いします。

もし使いにくかったりバグなどあったりしたら[issue](https://github.com/ogata-k/fakes-gen-cli/issues)に挙げてください。対応します。

最後まで見ていただきありがとうございました。