Forgeryの独自辞書でFabricateする

それぞれの言葉の意味を知らないとさっぱり想像もつかないタイトルになってしまった。

えーと Ruby でダミーデータを生成するためのツールを自分で拡張する話です。

Forgeryは独自辞書を持てる

どうもそうっぽいなぁというのはドキュメントを見てると想像がつくんだけど、具体的にどうしたらいいかはちょっとすぐには分からなかった。でもこれ見てだいたい分かった。

Forgery Gem, How to create Dictonaries and Forgeries « Ruby NYC

まとめると Ruby のコード的には

  • Forgery を継承したクラスを作る
  • そのクラスの中で dictionaries[:dictionary] と書くと symbol で書いた名前の、独自に定義した辞書ファイルの内容を読み込むことができる

ということらしい。

Rails 環境下のパスが載っているが、これはちょっと違うみたい。

独自Forgery用のディレクトリ

Rails 3.0.4 + Forgery 0.3.7 環境で

rails g forgery

とすると所定のディレクトリがダダッとできる。それが以下。

lib/
└── forgery/
       ├── dictionaries/
       ├── extensions/
       ├── forgeries/
       └── formats/

これを forgery のコード内では

require 'forgery/forgery_railtie'
  if Forgery.rails? && Rails::VERSION::STRING >= "3.0.0"

から

Forgery.load_from! "#{Rails.root}/lib/forgery"

こう繋いでいるので、

Forgery.load_from!( DIRECTORY )

としたら

DIRECTORY/
├── dictionaries/
├── extensions/
├── forgeries/
└── formats/

こういうディレクトリの中から forgery クラスや辞書を探すという動きをする。

独自Forgeryクラスの定義方法

上の記事のサンプルでは

class MyForgery < Forgery
  ...
  def self.method
    ...
  end
  ...
end

のような形になってるんだけど、これは

class Forgery::My < Forgery
  ...
  def self.method
    ...
  end
  ...
end

にしておくと、Alternate syntax で

Forgery(:my)

のように呼び出すことができる。

メソッドはクラスメソッドにしておくとスムーズに呼び出し可能。

独自辞書の定義と利用

例えば以下のようにファイルを置いた場合には

DIRECTORY/
└── dictionaries/
       ├ foo
       └ bar

以下のように呼び出すことができる。

class Forgery::My < Forgery
  ...
  def self.method
    ...
    dictionaries[:foo]
    dictionaries[:bar]
    ...
  end
  ...
end

辞書ファイルは

  • 拡張子なし
  • 1行1項目

で書く。

dictionaries の戻り値は Array なので Array のメソッドがいろいろ使える。

Fabricatorからどう使うか

同じく Rails 環境のまま話を進めると

rails g fabrication:model NAME

が使えるので、指示通りに作ると

spec/fabricators/NAME_fabricator.rb

ファイルができる。まだ試してないのでよく分からないけど、ここで Fabricator を定義しておいて spec の中で Fabricate して使えということらしい。しかしここで個人的には疑問があって、

  1. fabricator を fixture_replacement にしてしまうと spec 走るたびにデータが変わっちゃって、テスト書きにくくない?
  2. 正しく意図通りに fabricate できてるかどうかすぐにチェックできなくてもどかしくない?

の二点がすごく気になっている。

easy_fabricatorを使う

上の疑問については自分で解決できなかったので、先日作った easy_fabricator を使うようにすると少しマシかなと思っている。

require 'forgery'
Forgery.load_from!( DIRECTORY )

を書いてやれば独自定義の辞書を使った独自 Forgery クラスが利用できるので、これを書き足したうえで

script/easy_fabricator

として置いてみた。うむ、これは便利だな。辞書を定義している途中経過とかで確認しやすい。

これでできあがったものを CSV や YAML で吐いてそのまま fixture として利用してもいいんだし。というか、実は最初からそのつもりで easy_fabricator を書いたんだけど。

まとめ

なんとか独自の辞書を使ったダミーデータを作れるようになった。まだ辞書が足りないので十分に活用できていないが、地味に地味によくしていく予定。

それはともかく、

動的にダミーデータを生成する場合のテストってどう書くのがいいのか、誰か教えてください。

もう一つ。

独自クラス独自辞書を追加するためのgemができたら便利だよね。

More