Skip to content
baban edited this page Jun 19, 2013 · 1 revision

This document is translating now

Getting started

このgemはrailsでの開発中に感じたfixturesに関する多数の不満を一括して解決するために作られました。 主な理由はfixtureの編集のしずらさと、動的なデータの扱いのしづらさですが、細かい不満点は挙げていくとキリがないので、ここでは飛ばすとして、実際に一つの案件をこなしてみて、どの様に使っていくのかを体験して行きましょう

インストール

もしあなたがすでにrailsのプロジェクトを作って、webアプリケーションを開発中であれば、導入は簡単です Gemfileに次の1行を追加してbundle installを行えば、導入は完了します

gem 'flextures'

ただ実際には、人によって作っているアプリケーションの種類は違うと思いますので 説明するための代表としてRPG風のソーシャルゲームを想定して、作業を進めて行かせていただきましょう

テーブルの準備

本当はもっと多くのテーブルがあるのですが、ここでは簡単のためにテーブルの次の部分だけを取り出します

  • usersテーブルには、ユーザーの体力などのステータスを記録する
  • ユーザーはアイテムを持っているテーブルと1対多の関連で繋がっている

db/migrate/20110516035555_create_users.rb

class CreateUsers < ActiveRecord::Migration
  def self.create
    create_table :users do |t|
      t.string   :name,           default: "", null: false
      t.integer  :sex,            default: 0,  null: false
      t.text     :profile_comment,default: ""
      t.integer  :level,          default: 1,  null: false
      t.integer  :exp,            default: 0,  null: false
      t.integer  :guild_id,       default: 0,  null: false
      t.integer  :hp,             default: 0,  null: false
      t.integer  :mp,             default: 0,  null: false
      t.integer  :max_hp,         default: 1,  null: false
      t.integer  :max_mp,         default: 1,  null: false
      t.integer  :attack,         default: 1,  null: false
      t.integer  :defence,        default: 1,  null: false
      t.integer  :base_attack,    default: 1,  null: false
      t.integer  :base_defence,   default: 1,  null: false
      t.timestamps
    end
  end
end

db/migrate/20110516035565_create_items.rb

class CreateItems < ActiveRecord::Migration
  def self.create
    create_table :items do |t|
      t.integer  :user_id,        null: false
      t.integer  :master_item_id, null: false
      t.integer  :count,          default: 0, null: false
      t.integer  :used_count,     default: 0, null: false
      t.timestamps
    end
  end
end

rakeコマンドからの呼び出し

まずは、railsアプリケーションのTOPディレクトリに移動して、次のコマンドを実行して下さい

bundle exec rake -T

そうすると現在使用出来るrakeコマンドの一覧が表示されますが、その中に次の3つのコマンドが追加されています

rake db:flextures:load      # load fixture data csv format
rake db:flextures:dump      # Dump data to csv format
rake db:flextures:generate  # load and dump file (replace) new data file

また、Rspecなどのテスト・ツールからも呼び出す事ができます そのため快活環境と、テスト環境で同じデータでテストを行う事ができるようになっています 実際にこれらの機能を触りながら体験して行きましょう

まずは、何をおいてもユーザーを作成しないといけません

Railsではユーザーのデータは users テーブルに格納するのが通例となっていますので ユーザーのデータを作成しましょう rake コマンド からflexturesを呼び出します

rake db:flextues:dump TABLE=users

こうすると spec/fixtures/ 以下に users.csv というファイルが作成されます 中身を見てみましょう

id,name,sex,profile_comment,level,exp,guild_id,hp,mp,max_hp,max_mp,attack,defence,base_attack,base_defence,created_at,updated_at

ユーザーが現在0人なので、テーブルのカラム名だけがダンプされています ここでExcelを開いて各々のユーザーのデータを打ち込んでいってもいいのですが、もう少しスマートな方法を取りましょう Flexturesでは、データを読み込むときに"フィルタ"という自分で読み込み機能をカスタマイズさせるためのプログラムを通過させます なので以下の様な仕様でフィルタを作成します

  • HP,MP,attack,defence などはみんな同じデフォルトの値を設定される
  • ユーザーは登録時に、アイテムを2個付与される
  • 名前と性別はランダムに勝手に作ってくれる
Flextures::Factory.define :users do |f|
  f.name=Faker::Japanese::Name.name unless f.name
  f.sex=[0,1].sample unless f.sex
  f.max_hp = f.hp = 100 unless f.max_hp.zero?
  f.max_mp = f.mp = 30 unless f.max_mp.zero?
  f.attack = 30 if f.attack.zero?
  f.defence = 30 if f.defence.zero?
  f.items<< [ Item.new( master_item_id:1, count:5 ), Item.new( master_item_id:2, count:5 ) ] if f.items.empty?
  f
end

経験上、簡単な同値クラステストと境界値テストでしたら10〜50人程度(少ないほど良い)のデータがあれば十分なので とりあえず10人作ってみて、足りない場合少しづつ増やしていくスタイルで行かせていただきましょう 先ほど作った spec/fixtures/users.csv を編集して次のように書き足します

id,name,sex,profile_comment,level,exp,guild_id,hp,mp,max_hp,max_mp,attack,defence,base_attack,base_defence,created_at,updated_at 1 2 3 4 5 6 7 8 9 10

そして次の様にコマンドを実行します

rake db:flextures:load TABLE=users
rake db:flextures:dump TABLE=users,items

これでフィルタを実行したデータが読み込まれて、吐き出しをされます 結果 spec/fixtures/users.csv には次のようなデータが吐き出されます

id,name,sex,profile_comment,level,exp,guild_id,hp,mp,max_hp,max_mp,attack,defence,base_attack,base_defence,created_at,updated_at
1,相米 初栄,0,,1,0,0,100,30,100,30,1,1,1,1,2013-06-18 14:53:36 UTC,2013-06-18 14:53:36 UTC
2,楳林 良枝,1,,1,0,0,100,30,100,30,1,1,1,1,2013-06-18 14:53:36 UTC,2013-06-18 14:53:36 UTC
3,南場 寛平,1,,1,0,0,100,30,100,30,1,1,1,1,2013-06-18 14:53:36 UTC,2013-06-18 14:53:36 UTC
4,加野 掬太郎,1,,1,0,0,100,30,100,30,1,1,1,1,2013-06-18 14:53:36 UTC,2013-06-18 14:53:36 UTC
5,真砂 成彰,0,,1,0,0,100,30,100,30,1,1,1,1,2013-06-18 14:53:36 UTC,2013-06-18 14:53:36 UTC
6,常陽 真幸,0,,1,0,0,100,30,100,30,1,1,1,1,2013-06-18 14:53:36 UTC,2013-06-18 14:53:36 UTC
7,上濱 純孝,1,,1,0,0,100,30,100,30,1,1,1,1,2013-06-18 14:53:36 UTC,2013-06-18 14:53:36 UTC
8,乙辺 充宏,1,,1,0,0,100,30,100,30,1,1,1,1,2013-06-18 14:53:36 UTC,2013-06-18 14:53:36 UTC
9,金沢 昌恵,1,,1,0,0,100,30,100,30,1,1,1,1,2013-06-18 14:53:36 UTC,2013-06-18 14:53:36 UTC
10,野塩 敏惠,1,,1,0,0,100,30,100,30,1,1,1,1,2013-06-18 14:53:36 UTC,2013-06-18 14:53:36 UTC

また、 spec/fixtures/items.csv にもデータが生成されて吐き出されます

id,user_id,master_item_id,count,used_count,created_at,updated_at
1,1,1,5,2,2011-11-12 00:00:00 UTC,2011-11-12 00:00:00 UTC
2,1,2,0,3,2011-11-12 00:00:00 UTC,2011-11-12 00:00:00 UTC
3,1,3,2,4,2011-11-12 00:00:00 UTC,2011-11-12 00:00:00 UTC
4,2,2,2,5,2011-11-12 00:00:00 UTC,2011-11-12 00:00:00 UTC
...以下アイテムのデータ

このようにしてデータを作成して、だいたい欲しい形のデータを作れたら、ここで使ったデータは単体テスト中でも使えますので あとは開発を進めていく中でデータを詰めて行きましょう

テストでのflexturesの使用方法

このようにして作られたデータはRspec等のテストツールの内側からも呼び出すことができます 今回は先程作ったデータを元に"User#levelup"メソッドのテストを記述しましょう

levelupメソッドの中身ですが今回は複雑な事は避けたいので、次のような作りになっています

class User < ActiveRecord::Base
  has_many :items
  # ユーザーのステータスを上昇させます
  # @params [Integer] level レベルの上昇分
  # @return [Integer] 上昇後のレベル
  def levelup( level = 1 )
    level.times do
      self.level += 1
      self.max_hp += 5
      self.max_mp += 3
      self.base_attack += 3
      self.base_defence += 3
    end
    self.save
    self.level
  end 
end

引数で上昇した文のレベルを渡してやると、その分だけステータスが上昇します

これに対して次の様にテストを記述します

require 'spec_helper'
describe User do
  describe "#user" do
    flextures :users
    before do
      @before_user = User.first
      @user = User.first
      @user.levelup
    end
    it "max_hpが上昇している" do
      @user.max_hp.should > @before_user.max_hp+3
    end
  end
end

テストの中で書かれている flextures :user の箇所でテストデータの読み込みがされます flexturesはYAMLよりもCSVを優先するので users.csv を読み込んでからテストを実行してくれます