ハコヅミを作る #43:キャンプで作る料理を選ぶと、食材が持ち物チェックに入る

前回(#42)で、料理を登録できるようになりました。今回は、料理をキャンプにつなぎます。

  • キャンプで料理を選ぶと、食材が持ち物チェックに入る(#188)
  • 選び直したときの、項目の足し引き
  • たまに落ちるテストと、止まったデプロイ

キャンプの持ち物=プランの中身+料理の食材

今までは、キャンプの持ち物は、選んだプランの中身でした。ここに、選んだ料理の食材を足します。

食材は消耗品なので、持ち物チェックの消耗品の項目になります。先に決めたことは、次のとおりです。

  • 並べ方は、今までどおりコンテナごと。料理ごとには並べない
  • プランにも入っている食材、2つの料理で使う食材は、1つの項目にまとめる(数量は足さない)
  • 進み具合や、コンテナの一括チェックも、ほかの消耗品と同じに扱う

料理ごとに並べる案もありました。ただ、ハコヅミは、車に積み込む順に並べるアプリです。卵はクーラーボックスに、カレールーはキッチンの箱に入ります。積むときに見たいのは、箱ごとの一覧です。

料理ごとの見え方は、別の場所に作ることにしました。


選んだ時点で、固定する

持ち物チェックの項目は、作った時点のプランの中身で固定しています(#8)。あとでプランを変えても、作ったキャンプは変わりません。

料理も、同じ考えにしました。項目は、料理を選んだ時点の食材で固定する。あとで料理の食材を変えても、作ったキャンプは変わりません。

そのために、「選んだ時点の、料理と食材の組」を持つテーブルを足しています。

テーブル 役割
camp_dishes そのキャンプで作る料理
camp_dish_supplies 料理を選んだ時点の、料理と食材の組

もう1つ、今ある項目のテーブルに、列を足しました。「プランから来た項目か」の印です。これが要る理由は、次の話です。


選び直したときの、足し引き

行く前に、料理を変えることがあります。カレーをやめて、鍋にする。このとき、項目をどうするか。

プランを変えたときは、項目を作り直して、チェックを全部外しています(#15)。荷物を最初から見直すためです。

料理は、そうしませんでした。料理を1つ変えただけで、テントのチェックまで外れるのは、やりすぎです。食材の足し引きだけを行い、ほかのチェックは残すことにしました。

足すほうは、単純です。増えた料理の食材のうち、まだ項目にないものを足します。

外すほうが、難しいところでした。カレーを外したとき、玉ねぎの項目を消してよいか。

  • 玉ねぎが、プランにも入っているなら、消してはいけない
  • 残ったほかの料理でも使うなら、消してはいけない

外すのは、「外した料理の食材のうち、プランから来た項目でなく、残った料理の食材でもないもの」だけです。ここで、さっきの印を使います。

この計算は、画面やデータベースから切り離して、1つの関数にしました。ユニットテストは 26 件あります。料理を入れ替えたとき、両方の料理に入っている食材は、足しも外しもしない(チェックが残る)、といった細かい動きも、ここで確かめています。


画面イメージで、置き場所を選ぶ

キャンプの画面の「料理」

料理ごとの見え方は、キャンプの画面に作ります。置き場所は、3つの案で届きました。

キャンプの画面の画面イメージが3つ並んでいる。案Aは、キャンプ情報のカードと持ち物チェックの間に、料理のカードを置いたもの。案Bは、キャンプ情報のカードの中に、料理の行を入れたもの。案Cは、持ち物チェックの下に、料理のカードを置いたもの。どれも、ポークカレーの行が開いていて、食材の名前とレシピの手順が見えている

左から、案A(間に置く)、案B(キャンプ情報の中)、案C(持ち物チェックの下)

Claude Code のおすすめは、案A でした。選んだのは、案B です。

料理は、キャンプ場や日付と同じ「このキャンプの情報」です。カードが1つ増えるより、中に入っているほうが、すっきりします。画面の上から「どこに行く、何を作る、何を積む」の順に読めます。

登録の画面の「作る料理」

登録・編集の画面の欄は、おすすめが「プランのすぐ下」でした。持ち物を決める欄を、上にまとめる考えです。

ここは、案にない場所を頼みました。画像の欄の下です。

キャンプを登録するとき、最初に決まっているのは、日付とキャンプ場です。何を作るかは、そのあとで考えます。入力の順番は、考える順番に合わせたいところです。

キャンプの登録の画面。プラン、予定期間、キャンプ場の名前・住所・電話番号・URL・地図の URL、メモ、画像と「または、画像の URL」の欄が並び、一番下に「作る料理」の欄がある。コーヒー(食材なし)、ポークカレー(食材 3 件)、ホットサンド(食材 2 件)にチェックが入っている

キャンプの登録の画面。「作る料理」は、一番下に置いた

ついでに、1つ直してもらいました。画像を URL から取り込む欄の名前です。ギアの画面と同じ「または、画像・商品ページの URL」になっていました。キャンプ場に、商品ページはありません。キャンプの画面では「または、画像の URL」にしています。

できあがり

キャンプの画面。キャンプ情報のカードの中に、予定期間・実績期間・キャンプ場の下に「料理」があり、コーヒー(食材なし。開いていて「レシピは未入力です。」)、ポークカレー(食材 1 / 3)、ホットサンド(食材 2 / 2・そろった。緑の文字)が並ぶ。その下に持ち物チェックがあり、クーラーボックスとコンテナなしの項目が並んでいる

キャンプの画面。料理ごとに、食材がいくつそろったかが分かる

料理の行には、食材がそろった数を出します。全部そろうと、緑で「そろった」と出ます。押すと開いて、食材の名前とレシピが読めます。

食材のない料理は、最初は「食材 0 / 0」と出ていました。意味は合っていますが、読んで分かりません。「食材なし」に変えてもらいました。


E2E が、1回だけ落ちる

PR を作ると、CI の E2E が1つ落ちました。料理とは関係のない、送信の回数の制限のテストです(#35)。

テストは、「1分に 300 回まで」の制限に対して、310 回送って、断られることを確かめていました。落ちたときは、310 回送っても、1回も断られていません。

原因は、数える枠の区切りでした。回数の制限は、1分ごとの枠で数えます。送っている途中で枠が切り替わると、数が 0 に戻ります。前の枠で 200 回、次の枠で 110 回なら、どちらも 300 に届きません。

テストを、次の形に書き直してもらいました。

  • 回数を決め打ちにせず、断られるまで送る
  • 断られるまでに、300 回以上は通っていること(制限が早すぎない)
  • 600 回までには、必ず断られること(枠をまたいでも、2つ分で届く)

「たまに落ちる」テストは、流し直せば通ります。ただ、それで済ませると、次に落ちたときに、本物の失敗と見分けられません。原因が分かるうちに直しました。


デプロイが、始まらない

マージすると、今度はデプロイが止まりました。テストは通っているのに、デプロイのジョブが「待ち」のまま動きません。15 分たつと、キャンセルされます。流し直しても、同じです。

調べてもらうと、原因は GitHub の側でした。GitHub Actions の障害で、ジョブを動かす機械が割り当てられない状態です。15 分は、こちらの設定の上限でした。デプロイが途中で固まったときに、止めるためのものです。

ここで決めたことは、2つです。

  • 上限は延ばさない。障害のために延ばすと、本当に固まったときに止まらなくなる
  • 手元からはデプロイしない。「反映は、PR のマージから CI で行う」という決まりは、急ぐ理由がないかぎり、破らない

ステップは1つも動いていないので、開発環境は前のデプロイのままです。壊れてはいません。待つことにしました。

障害は、数時間続きました。そのあいだは、コードを書かない相談を進めています。その話は、次回と次々回です。


おわりに

  • 並べ方は、使う場面に合わせる。積むときは箱ごと、作るときは料理ごと。1つの一覧で両方を満たそうとしない
  • 「あとから変えたとき」を、先に決める。足すより、外すほうが難しい
  • ややこしい足し引きは、画面から切り離して、関数とユニットテストにする
  • 入力の順番は、考える順番に合わせる
  • 時間の区切りに頼るテストは、区切りをまたいでも通る形にする
  • 外の障害で止まったときは、守りの設定や決まりを、その場でゆるめない

次回は、止まっているあいだに決めた、フリーと有料の違いです。

← トップページに戻る