【rails】factory_botでダミーデータ作り

※本サイトで紹介している商品・サービス等の外部リンクには、アフィリエイト広告が含まれる場合があります。

factory_botで簡単・便利にダミーテータを作成する

実際の開発環境では大量のダミーデータを使用する

毎回書くのは大変なので、factory_botを使って、もっと簡単にダミーデータが使えるようにする


factory_botをインストールする

gemfileに追加する

group :development, :test do
   #中略
  gem 'factory_bot_rails', '5.1.1'
end

(バージョンは講義にあわせてます)

bundle install


spec/rails_helper.rbに以下を追記する

  config.include FactoryBot::Syntax::Methods

これを書かないとFactory_botが使えない


factoriesフォルダを作成する

factoriesのファイルは複数形にする(慣例)


userに関するダミーデータ作り

spec/factoriesのフォルダの中にusers.rbのファイルを作る

userというfactoryを作る

FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }
    password { 'password' }
  end
end

define・・・「定義する」

上記の記述でUserモデルの設定を読み込んでくれる(ファイル名「users」で探してくれている?)


ダミーデータを使いたいところに入れる

spec/models/article_spec.rbを開く

RSpec.describe Article, type: :model do
  let!(:user) do
    user = User.create!({
      email: 'test@example.com',
      password: 'password'
    })
  end

↑の:userを定義している部分を↓のように書き換えるだけ

RSpec.describe Article, type: :model do
  let!(:user) { create(:user) }

すっきり!

:userを指定することで、factories:userから読み込んでくる


コードを実行してみる

bundle exec rspec spec/models/article_spec.rb

ちゃんと成功!!


コードを書き換える

:usercreateするとき、email: 'test@test.com'と書き加えることで

RSpec.describe Article, type: :model do
  let!(:user) { create(:user, email: 'test@test.com') }

factoriesに登録されているemailの値を書き換えることができる

  factory :user do
    email { Faker::Internet.email }

Fakerが作るはずのランダムなメールアドレスを'test@test.com'にすることができる


コードを実行してみる

    it '記事を保存できる' do
      puts user.email
      expect(article).to be_valid
    end

puts user.emailを追加して、本当にemailの値が書き換えられているか、コードの実行結果を見てみる

メールアドレスが書き換えられている!

※emailの指定は必要ないので「email: 'test@test.com'」は削除しておく


articleに関するダミーデータ作り

spec/factoriesのフォルダの中にarticles.rbのファイルを作る

FactoryBot.define do
  factory :article do
    title { Faker::Lorem.characters(number: 10) }
    content { Faker::Lorem.characters(number: 300) }
  end
end

ダミーデータを使いたいところに入れる

spec/models/article_spec.rbを開く

  context 'タイトルと内容が入力されている場合' do
    let!(:article) do
      article = user.articles.build({
        title: Faker::Lorem.characters(number: 10),
        content: Faker::Lorem.characters(number: 300)
      })
    end
    it '記事を保存できる' do
      expect(article).to be_valid
    end
  end

  context 'タイトルの文字が一文字の場合' do
    let!(:article) do
      article = user.articles.create({
        title: Faker::Lorem.characters(number: 1),
        content: Faker::Lorem.characters(number: 300)
      })
    end
    it '記事を保存できない' do
      expect(article.errors.messages[:title][0]).to eq('は2文字以上で入力してください')
    end
  end

上記をそれぞれ書き換えていく


①タイトルと内容が入力されている場合

articleはuserに紐づいているので、user: userと書いてcreate(:user)と紐づけることができる

RSpec.describe Article, type: :model do
  let!(:user) { create(:user) }

  context 'タイトルと内容が入力されている場合' do
    let!(:article) { build(:article, user: user) }


②タイトルが1文字の場合

title: Faker::Lorem.characters(number: 1)と書くことで、タイトルを1文字に書き換える

  context 'タイトルの文字が一文字の場合' do
    let!(:article) { build(:article, title: Faker::Lorem.characters(number: 1), user: user) }

    before do
      article.save
    end
    
    it '記事を保存できない' do
      expect(article.errors.messages[:title][0]).to eq('は2文字以上で入力してください')
    end
  end
なぜcreateじゃなくてbuildなのか?
  1. ここで使われているcreateはrubyにおけるcreate!と同じ意味のものになる
  2. create!だと、例外が発生して処理が止まってしまう
  3. 「1文字だから保存できない」ことを確認したいのに、「1文字だから保存できない」という例外で処理が止まる
  4. buildを使うと処理が止まることなく動く
  5. buildを使うので、saveも必要になる

ダミーデータは書いているとどんどん長くなるけど、factory_botを使うことでとてもすっきりする

#DAY13