---
title: FactoryBot筆記
description: 語法
robots: noindex, nofollow
lang: zh-tw
dir: ltr
breaks: true
tags: FactoryBot
disqus: hackmd
---
# 基礎應用
[基礎篇](https://devhints.io/factory_bot)
[Github FactoryBot Getting Started](https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md)
## Setting
Rspec 就不用再輸入`FactoryBot`直接`create(:xxx)`即可
```ruby=
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
```
Cucumber
```ruby=
# env.rb (Rails example location - RAILS_ROOT/features/support/env.rb)
World(FactoryBot::Syntax::Methods)
```
將 Factory 設定在以下路徑 `FactoryBot.find_definitions` 會自動找到此路徑加載 Factory
```ruby=
test/factories.rb
spec/factories.rb
test/factories/*.rb
spec/factories/*.rb
```
## 基礎
使用範例:
```ruby=
# This will guess the User class
FactoryBot.define do
factory :user do
first_name { "John" }
last_name { "Doe" }
admin { false }
end
end
```
上述所說會去猜測是否有 User 這個 class 然後依照你 Model欄位來寫attributes 最後幫你建出一筆 user。花括弧可省略
```ruby=
# This will use the User class (otherwise Admin would have been guessed)
factory :admin, class: "User"
```
意思是你也可以替factory指定其他名稱但必須指定他屬於哪個class
### 建立bot
factory_bot supports several different build strategies: build, create, attributes_for and build_stubbed:
```ruby=
# Returns a User instance that's not saved
user = build(:user)
# Returns a saved User instance
user = create(:user)
# Returns a hash of attributes that can be used to build a User instance
attrs = attributes_for(:user) # {name: 'CK', phone: '123'}
# Returns an object with all defined attributes stubbed out
stub = build_stubbed(:user)
# Passing a block to any of the methods above will yield the return object
create(:user) do |user|
user.posts.create(attributes_for(:post))
end
```
create => 真的寫進db
build => 還沒save 且 id為 nil
build_stubbed => stub的概念創建一個假的實體而且還有id
如果不懂build、create、build_stubbed的可以看看這篇
[FactoryGirl create vs build vs build_stubbed](https://blog.gmifly.tw/2019/04/14/Rspec-FactoryGirl-vs-create-vs-build-vs-build-stubbed/)
[attributes_for看不懂看這篇](https://stackoverflow.com/questions/13150272/meaning-for-attributes-for-in-factorygirl-and-rspec-testing)
### Aliases
不常使用,用法其實就是association的概念只是縮寫
```ruby=
factory :user, aliases: [:author, :commenter] do
first_name { "John" }
last_name { "Doe" }
date_of_birth { 18.years.ago }
end
factory :post do
# 寫法等同於 association :author, factory: :user
# 寫法等同於 association :user
author
title { "How to read a book effectively" }
body { "There are five steps involved." }
end
```
不過這邊不推薦使用`association`因為他會在你建立這筆bot時也將有關聯的bot一同建立出來, 建議使用 `trait`
### Dependent Attributes
可以定義動態區塊在建立bot時在指定值
```ruby=
factory :user do
first_name { "Joe" }
last_name { "Blow" }
email { "#{first_name}.#{last_name}@example.com".downcase }
end
create(:user, last_name: "Doe").email
# => "joe.doe@example.com"
```
### Transient(目前搞不出來,測試中)
不常使用,可以定義不是attributes的值拿來判斷或是存放值
```ruby=
factory :user do
transient do
rockstar { true }
end
name { "John Doe#{" - Rockstar" if rockstar}" }
end
create(:user).name
#=> "John Doe - ROCKSTAR"
create(:user, rockstar: false).name
#=> "John Doe"
```
```ruby=
factory :car do
transient do
# capitalize is not an attribute of the car
capitalize false
end
name { "Jacky" }
purchase_price { 1000 }
model { "Honda" }
after(:create) do |car, evaluator|
car.name.upcase! if evaluator.capitalize
end
end
car = FactoryGirl.create(:car, capitalize: true)
car.name
# => "JACKY"
```
[這邊有更詳細的講解](https://stackoverflow.com/questions/38573131/what-is-the-purpose-of-a-transient-do-block-in-factorybot-factories)
## 其他相關文件
[FactoryBot在4.11之後刪除所謂的靜態屬性](https://thoughtbot.com/blog/deprecating-static-attributes-in-factory_bot-4-11)(目前我還沒實測出來)