「Everyday Rails - RSpecによるRailsテスト入門」翻訳者チームの伊藤です。
Everyday Railsを読んでいただき、どうもありがとうございます。
ご質問の件について、できるだけ詳しく説明してみますね。
なお、以下のサンプルコードはEveryday RailsのGitHubリポジトリから抜粋しています。
https://github.com/everydayrails/everydayrails-rspec-2017
ブロック内の|project|
これはFactoryBotによってcreateされたProjectのインスタンスが渡されます。
もしproject = FactoryBot.create :project, :with_notes, name: 'Foo'
というコードがあれば、まずFactoryBot.create :project, name: 'Foo'
を呼びだしたのと同じようにProjectのインスタンスが作成され、そのインスタンスがtrait :with_notes
の中の|project|
に渡ってきます。
project: project
これはcreate_list
メソッドで作成されるNoteクラスのインスタンスに関連するProjectクラスのインスタンスの指定です。
Noteクラスの定義は次のようになっているので、何らかのProjectに属する必要があります。
ruby
1class Note < ApplicationRecord
2 belongs_to :project
3 belongs_to :user
4
5 # ...
つまり、FactoryBot.create :project, :with_notes
をtraitなしで書こうとすると、こんなイメージになります。
project = FactoryBot.create :project
5.times do
FactoryBot.create :note, project: project
end
なお、ProjectとNoteのファクトリは以下のような定義になっています。
ruby
1FactoryBot.define do
2 factory :project do
3 sequence(:name) { |n| "Project #{n}" }
4 description "A test project."
5 due_on 1.week.from_now
6 association :owner
7
8 trait :with_notes do
9 after(:create) { |project| create_list(:note, 5, project: project) }
10 end
11
12 # ...
13 end
14end
15
16FactoryBot.define do
17 factory :note do
18 message "My important note."
19 association :project
20 user { project.owner }
21
22 trait :with_attachment do
23 attachment { File.new("#{Rails.root}/spec/files/attachment.jpg") }
24 end
25 end
26end
FactoryBotをまったく使わずに書くなら、次のようなイメージになります。
ruby
1owner = User.create!(
2 first_name: "Aaron",
3 last_name: "Sumner",
4 email: "tester1@example.com",
5 password: "dottle-nouveau-pavilion-tights-furze"
6)
7
8project = Project.create!(
9 name: "Project 1",
10 description: "A test project.",
11 due_on: 1.week.from_now,
12 owner: owner
13)
14
155.times do
16 Note.create!(
17 message: "My important note.",
18 project: project,
19 user: project.owner
20 )
21end
こんな説明でいかがでしょうか?
何か不明な点があればまたご質問ください。
追記
あ、たしかにFactoryBot.
を付け忘れてましたね。すいません。コードの方は修正しておきました。
ちなみにspec/rails_helper.rb
にconfig.include FactoryBot::Syntax::Methods
という設定を入れておくとFactoryBot.
が省略できます。(参考)
僕はふだんこのスタイルでFactoryBotを使ってます。
コメントに載っていたコードですが、
ruby
1it "userが作成されたらprojectが5個作成される" do
2 project = FactoryBot.create(:user, :with_projects)
3 expect(project.projects.length).to eq 5
4end
は、
ruby
1it "userが作成されたらprojectが5個作成される" do
2 user = FactoryBot.create(:user, :with_projects)
3 expect(user.projects.length).to eq 5
4end
というように変数名をuser
にした方がわかりやすいと思いました。
それ以外はOKだと思います????
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/29 10:40
2020/05/30 01:25