Userにbelong to で紐づくデータをseed_fuで作るときにeach_with_indexが活躍した

June 27, 2021

こんにちは、たわらです。

今回は業務で学んだお話です。

背景

User に belong to で紐づく seed データを作成する必要がありました。 たとえばこんな感じ。業務コードをだいぶぼかしているので変な感じするかもですが目をつむってください。

UserNickname.seed do |s|
  s.id = 1
  s.user_id = User.find_by(email: "user_001@bt.com")
  s.nickname = "hogetarou"
end

で、50 人いる user の seed データすべてに nickname をーー同じでもーー付与しなければならない。

愚かな対処

ボクはなにも考えずに 50 人分全員ベタ打ちで対処した。長い時間をかけて、こんなのエンジニアらしくないと頭では思いながら、、、

UserNickname.seed do |s|
  s.id = 1
  s.user = User.find_by(email: "user_001@bt.com")
  s.nickname = "hogetarou"
end

UserNickname.seed do |s|
  s.id = 2
  s.user = User.find_by(email: "user_002@bt.com")
  s.nickname = "hogetarou"
end

.
.
.

UserNickname.seed do |s|
  s.id = 50
  s.user = User.find_by(email: "user_050@bt.com")
  s.nickname = "hogetarou"
end

先輩のご指摘

PR レビューをすると「User.all を each で回して作成する方が良さそう」とコメントされる。

なんと、その手があったか!

で、こんなふうに書いた。300 行くらいあったコードがわずか 10 行程度になりました。すごい。

seed_id = 1
User.all.each do |user|
  UserNickname.seed do |s|
    s.id = seed_id
    s.user_id = user.id
    s.nickname = "hogetarou"
  end
  seed_id += 1
end

each_with_index の登場

「Ruby っぽくないコードになっちゃってるね。each_with_index を使うといいよ」と先輩が PR に再度コメントした。細かいところまで見てもらえてうれしい。seed_id += 1 のところらへんが Ruby ならもっとうまく書けるとのこと。

なるほど、each_with_index (!) どこかで読んだことあるメソッドだった。先輩に聞きながら実装すると、こんなふうになった。

User.all.each_with_index do |user, i|
  UserOrigin.seed do |s|
    s.id = i + 1
    s.user_id = user.id
    s.nickname = "hogetarou"
  end
end

要素とそのインデックスをブロックに渡して、インデックスをブロック内で使えるのですね。 ちなみにインデックスは 0 からはじまるので、id など 1 から開始したい場合はi + 1とします。

ひとこと

ベタ打ちで時間をかけて書いたコードがとてもすっきりとしました。時間を無駄にしてしまいましたが、「そういう経験も意外と大事だよ」と先輩は言います。たしかに長いコードを短くできた快感がありました。いい経験ができました。

参考文献

https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/each_with_index.html