Every day is a new day.

webエンジニアになりたい55歳の私の記録

Buzzcordのランキング表示のバグを修正しました👍

はじめに

こんにちは。Paruです。フィヨルドブートキャンプを今年6月に卒業しました。 bootcamp.fjord.jp

先月中旬に自作サービスの「Buzzcord」をリリースしました。 (詳しくはリリース記事をご覧ください)

github.com

paru871.hatenablog.com

今日はこのBuzzcordでバグが発生!そして修正した話を書きたいと思います。

目次

バグは急にやってきた

フィヨルドブートキャンプのDiscordサーバーでもこのBuzzcordを採用していただき、稼働がスタートして特に問題なく約10日間が過ぎた頃、、、 ある朝バグが発生しました!

ランキング表なのに、なぜか順位が4→5→1→2→3位の順で表示されています。

アプリの作成中も本番稼働してからもこんなことはありませんでしたし、ランキング順にきちんと表示されることを確認するテストも書いて毎回パスしてきました。

コードはこう書いていた

Railsのコントローラー内の記述はこうなっていました。

class RanksController < ApplicationController
  def index
    @ranks = Rank.includes(%i[emojis attachments])
  end
end

親となるRankのレコードを作成する際にソートをしてcreateしたので、関連するテーブルをまとめて取得しても、このRankレコードの生成順は保持されるとすっかり思い込んでいました😱😨😰

SQLを調べる

RailsのターミナルでのSQL文を見て、SELECTの挙動をドキュメントで確認しました。

SELECT "ranks".* FROM "ranks"

PostgreSQL 13.1文書より SELECT

ORDER BY句が指定された場合、返される行は指定した順番でソートされます。 ORDER BYが指定されない場合は、システムが計算過程で見つけた順番で行が返されます。(途中省略)

ORDER BY句を使うと、結果行を指定した式(複数可)に従ってソートすることができます。 最も左側の式を使って比較した結果、2つの行が等しいと判断された場合は、1つ右側の式を使って比較します。その結果も等しければ、さらに次の式に進みます。 指定した全ての式で等しいと判断された場合は、実装に依存した順番で返されます

なるほど、レコードの出力順に意味がある場合は、しっかりと順番を指定してやる必要があるのですね。知らなかったー、なぜ今まで順番指定しなくてもきちんとランキング順に表示されていたのでしょうか?

ドキュメントに書かれているように「システムが計算過程で見つけた順番」が偶然ずっとランキング順だったのでしょうか。不思議です。

このように修正した

というわけで、下記のように修正しました。 orderを使ってランキングの昇順を指定します。

class RanksController < ApplicationController
  def index
    @ranks = Rank.includes(%i[emojis attachments]).order('ranks.order asc')
  end
end

SQL文もこのようになりました。ORDER BYが指定されています。

SELECT "ranks".* FROM "ranks" ORDER BY ranks.order asc

今回バグが発生した、「トップに来ていた第4位」の投稿文には添付画像があったため、的外れかもしれませんが念の為、添付画像がある場合のランキング順のテストも追加しました。

修正してデプロイ後、ランキング順が正常に表示されたのを確認しました。 (すみません、修正後のスクショを撮るのを忘れてしまいました。)

考えたこと

  • 思い込みと偶然の積み重ねでバグに気づかずにいた数日前までの自分に喝を入れたいです🥺
  • ランキングのように必ず順位順に表示されるものは、モデルのdefault_scopeで常に順位の昇順になるように指定しておくのもよいのかもしれないと考えました。しかし調べてみるとdefault_scopeはかなり厄介な印象も受けるので慎重にやる必要がありそうです。

まとめ

以上、自作サービスでの目立つバグが初めての経験でかなり動揺しましたが、学び(特に苦手意識を持っていたSQLについて)を得ることができ修正もできましたので、ブログにて共有させていただきました。ご覧くださりありがとうございました。

今後もよりよいアプリになるよう学習していきますので、引き続きBuzzcordでお楽しみいただけましたら幸いです!

追記(2022/08/06)

今回のブログ公開のツイートに、メンターの伊藤さんがリプをくださいました!

とてもわかりやすい!
日頃からよく、「伊藤さんはいつでも私たち受講生が陥りがちな問題に先回りしてブログで説明してくださってる!」という話を輪読会仲間としているのですが、今回もまさにそれ!でしたー。
伊藤さんのQiitaブログの記事を再度読み込もうと心に誓いました👊