Rspec,FactoryBotのsequence

sequenceの書き方で疑問に思った事があったので書きました

環境
Rails 5.2.3
ruby 2.6.4

RSpecの基本において参考にしたのは以下

[使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」 - Qiita](https://qiita.com/jnchito/items/42193d066bd61c740612)

そんな中、自分が携わってる資料で出てきた
### **sequence(シーケンス)**

```ruby
FactoryBot.define do
  factory :task do

    sequence(:title, "title_1") # ← これ
    content { "content" }
    status { :todo }
    deadline { 1.week.from_now }
    association :user
  end
end
```



こいつが分からず詰まった。

他のcontent,status,deadline,associationは分かるのよ。コントローラーとモデルの中に書いてあるから。

タイトルはtitleじゃダメなの？ってところ

# ・前提として


まず、シーケンスとはなんぞや？

[thoughtbot/factory_bot](https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#sequences)

翻訳すると、

> グローバルシーケンス
特定の形式のユニークな値（例えば、電子メールアドレス）は、シーケンスを使って生成できます。シーケンスを定義するには、定義ブロックの中でsequenceを呼び出し、シーケンス内の値を生成するにはgenerateを呼び出します。

```ruby
# 新しいシーケンスの定義
FactoryBot.define do
  sequence :email do |n|
    "person#{n}@example.com"
  end
end

generate :email
# => "person1@example.com"

generate :email
# => "person2@example.com"

# 上記のようにnの部分の数が増えている
```

以下も参照

[FactoryBot(FactoryGirl)チートシート - Qiita](https://qiita.com/morrr/items/f1d3ac46b029ccddd017#%E9%80%A3%E7%95%AA%E3%82%92%E6%8C%81%E3%81%A3%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8Bsequence)

[インクリメントとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word1697.html)

モデルのvalidate内にuniqueness: trueというユニークの記載がある場合はこのシーケンスとやらを使えば良いようだ。

# ・疑問な点

しかし、自分が見ていた資料の中では

```ruby
# 元々書いてあったものが
sequence(:title) { |n| "title_#{n}" }

	　↓　↓

# この様に変更していた
sequence(:title, "title_1")
#    　　　↑第一引数  ↑ 第二引数
```

理由としては

> sequenceの第二引数で定義した文字にはループの度にString#nextを末尾の文字に実行される

[String#next (Ruby 3.0.0 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/String/i/next.html)

とリンク先を見るも、いまいち腹落ちせず…

### ？？？🤔 ？？？

こういった記事は見つけたので第二引数の事は分かったが

[FactoryBot (旧FactoryGirl) の sequence と .next - Qiita](https://qiita.com/kuboon/items/8897aca59dc968ca6d3c)

### なぜ "title_1" で認識してくれるのだろうか
【そういうもの】と思うしかないのか？

という疑問が浮かんだ。

あるslackに質問を投げてみたところ

String#next でnの部分を読んで(呼んで?)くれるコードを教えてもらった

[thoughtbot/factory_bot](https://github.com/thoughtbot/factory_bot/blob/v6.2.0/lib/factory_bot/sequence.rb#L30)

他の方からも

・「個人的にはブロックを使う方を好む」
・「個人的には、上の方が何が起こるかを予想しやすくて良い」

などと反応があった。

# ・解決への光明

そんな中、とある方がconsoleで

```ruby
~ irb
irb(main):001:0> 'title_1'.next
=> "title_2"
```

というString#nextの動きを検証してくれたのをきっかけに私の腑に落ちるのが始まる。

先程の[リファレンスマニュアル](https://docs.ruby-lang.org/ja/latest/method/String/i/next.html) の動きをやってくれたわけだ。

それを考慮して自分でやってみるとこうなった

```ruby
Loading development environment (Rails 5.2.3)
[1] pry(main)> 'title_1'.next
=> "title_2"  # titleは数字が変わる
[2] pry(main)> 'user_#{n}@example.com'.next
=> "user_\#{n}@example.con" # メールでは数字ではなくmがnになった
[3] pry(main)> 'user_{n}@example.com'.next
=> "user_{n}@example.con"
[4] pry(main)> 'user_n@example.com'.next
=> "user_n@example.con"
```

なので、[先程のリンク内](https://qiita.com/kuboon/items/8897aca59dc968ca6d3c)にある

> ブロックを渡さずに第二引数を渡すと、 .next が呼ばれるようになっている

となっていたので、メールを第一引数として.nextを呼んだわけだが、メールはnの部分の数字ではなく末尾の.comのmが.conのnに変わった。

つまり、.nextを呼んでもメールの中の数字が変わることがない(末尾じゃないから)

しかし、title_1を第二引数にしても2に変わる(末尾だから)

答えはすごくシンプルで

### title_1の場合は末尾だから数字が(+1)変わる
### メールは変えたい部分が末尾じゃないから途中のnの部分は変わらない。だからメールはブロック化して書いている。

なので"title_1"の書き方は

> 変えたい場所が末尾の場合のみ使える書き方

これで腑に落ちました。

振り返ると**"何でこんなに悩んでたんだろう"**と情けなくなります