【FactoryBot】ファクトリの生成方法（build, build_stubbed, create, attributes_for）

# はじめに
RSpecでテストを記述する際、ファクトリの生成方法にいくつか種類があり、混同したので一度整理してみる。

## 環境
Ruby 3.0.3
Rails 6.1.4
rspec-rails 5.0.2
factory_bot_rails 6.2.0

# 前提
factoryファイルを以下のように記述し、挙動を確認します。
（ユーザーが会社の情報を投稿できるようなアプリケーションを想定しています）

```ruby:spec/factories/companies.rb
FactoryBot.define do
  factory :company do
    sequence(:company_name) { |n| "company_#{n}" }   # 会社名
    company_overview { 'sample_overview' }           # 会社の概要
    company_address { 'sample_address' }             # 所在地
    company_num_of_emp { '100-150' }                 # 従業員数
    user
  end
end
```

```ruby:spec/factories/users.rb
FactoryBot.define do
  factory :user do
    name { Faker::Name.name }
    sequence(:email) { |n| "test#{n}@example.com" }
    password { Faker::Internet.password(min_length: 8) }
    password_confirmation { password }
  end
end
```
# ファクトリの生成方法
## build
* メモリ上にインスタンスを保存するだけでDBには保存しない
* `id` や `timestamp` には`nil`が指定される
* 関連先のデータはDBに保存されない
  * バージョンアップで変更された（[参考](https://qiita.com/TunaGinger/items/ca08b1eaa5c1e321e302)）

戻り値： **作成されたインスタンス**

```bash
> company = FactoryBot.build(:company)
> company
=> 
#<Company:0x00005576a19bdbe8
 id: nil,
 company_name: "company_1",
 company_address: "sample_address",
 company_overview: "sample_overview",
 company_num_of_emp: "100-150",
 created_at: nil,
 updated_at: nil,
 user_id: nil>

> company.user
=> #<User id: nil, provider: "email", uid: "", allow_password_change: [FILTERED], name: "Jen Schumm", company_id: nil, newgra_or_midcar: nil, eng_category: nil, admin: false, image: nil, email: "test1@example.com", created_at: nil, updated_at: nil>
```

## build_stubbed
* `id`には適当な値が指定される
* `timestamp`は実際の時間が指定される
* 関連先のデータはDBに保存されないがidが紐づけられる

戻り値： **作成されたインスタンス**

```bash
> company = FactoryBot.build_stubbed(:company)
> company
=>
#<Company:0x00005576a5d99e98
 id: 1002,
 company_name: "company_2",
 company_address: "sample_address",
 company_overview: "sample_overview",
 company_num_of_emp: "100-150",
 created_at: Sat, 05 Feb 2022 04:00:57.000000000 UTC +00:00,
 updated_at: Sat, 05 Feb 2022 04:00:57.000000000 UTC +00:00,
 user_id: 1001>

> company.user
=> #<User id: 1001, provider: "email", uid: "", allow_password_change: [FILTERED], name: "Julianne Hayes MD", company_id: nil, newgra_or_midcar: nil, eng_category: nil, admin: false, image: nil, email: "test2@example.com", created_at: "2022-02-05 04:00:57.000000000 +0000", updated_at: "2022-02-05 04:00:57.000000000 +0000">
```
## create
* インスタンスを作成したのち、DBに保存する

戻り値： **作成されたインスタンス**

```bash
> company = FactoryBot.create(:company)
...(データベースに保存)...
> company
=>
#<Company:0x00005576a5f60588
 id: 146,
 company_name: "company_3",
 company_address: "sample_address",
 company_overview: "sample_overview",
 company_num_of_emp: "100-150",
 created_at: Sat, 05 Feb 2022 04:02:27.000000000 UTC +00:00,
 updated_at: Sat, 05 Feb 2022 04:02:27.000000000 UTC +00:00,
 user_id: 7>

> company.user
=> #<User id: 7, provider: "email", uid: "test3@example.com", allow_password_change: [FILTERED], name: "Nancey Lemke", company_id: nil, newgra_or_midcar: nil, eng_category: nil, admin: false, image: nil, email: "test3@example.com", created_at: "2022-02-05 04:02:27.000000000 +0000", updated_at: "2022-02-05 04:02:27.000000000 +0000">
```
## attributes_for
* FactoryBot の定義から、値を Hash 形式で受け取る。

戻り値： **作成されたインスタンスのパラメータ（ハッシュ）**

```bash
> company = FactoryBot.attributes_for(:user)
> company
=> 
{:company_name=>"company_4",
 :company_overview=>"sample_overview",
 :company_address=>"sample_address",
 :company_num_of_emp=>"100-150"}
```

##参考
https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#using-factories

https://qiita.com/TunaGinger/items/ca08b1eaa5c1e321e302