ハコヅミを作る #62:ギアを共有できるようにする(スイッチの形を3回変えた、通報がないうちは出さない)

前回(#61)の最後に、「次回は、キャンプで使ってみた話」と書きました。その前に、キャンプのあとで作ったものの話を、先に書きます。ハコヅミに、はじめて「ほかの人に見えるもの」ができました。

  • テスタを待たずに、共有を作る
  • 仕組みを、1本にそろえる
  • ほかの人のデータを読む場所を、1つにする
  • スイッチの形を、3回変える
  • 見たいものが、同時に見えない
  • 通報がないうちは、出さない
  • 「見えません」と書いた文を、全部直す
  • Issue の本文を、空で上書きした

テスタを待たずに、共有を作る

ハコヅミは、10月7日にベータ版を始めて、テスタを募っています。次の段階は「テスタの意見を聞いて、直す」と決めていました。共有(ほかの人のギアを見られる機能)は、そのあとです。

共有を作る前に、テスタに聞きたいことがありました。「自分のギアを、人に見せたいですか」「人のギアを、見たいですか」。

ところが、これから冬になります。キャンプに行く人が減り、テスタの募集も、きびしくなりそうです。持ち物チェックは、実際にキャンプに行かないと試せません。春まで待つことになります。

待つあいだ、手を止めておくのは、もったいない。順番を入れ替えることにしました。

  • 共有を、先に作る
  • 春に来たテスタには、共有が入った形で触ってもらう
  • 「見せたいか」は、聞くのではなく、使われ方を見て直す

聞いてから作るはずだったものを、作ってから聞く形です。まちがっていたら、直せばよい。直せないのは、冬のあいだの時間のほうです。

出すのは、見るだけ

共有には、前に決めた2つの線があります。

  • 本人が共有にしたものだけが、見える
  • ほかの人は、見るだけ(変えられない)

見られるのは、ハコヅミにログインしている人だけです。検索のサイトには、載せません。写真や持ち物が入るので、狭いほうから始めます。

いいね、コメントは、入れていません。人どうしがやり取りする機能は、見張る仕事が増えます。1人で運営するうえで、どこまで持てるかを、まだ決めていないからです。


仕組みを、1本にそろえる

共有したいものは、3つあります。ギア、キャンプ(行き終わったもの)、料理。

前に考えた方針では、種類ごとに、切り替え方が違いました。

前の方針
ギア 全体で、共有する・しないを切り替える(1件ずつは選ばない)
キャンプ 1件ずつ切り替える
料理 1件ずつ切り替える

ギアは数が多いので、1件ずつ選ぶのは面倒。キャンプと料理は、1件ごとに事情が違う。それぞれに、理由はありました。

作り始める前に、こう頼みました。

「全てを共有」のトグルボタンと、個別の「共有」のトグルボタンを配置し、個別に共有したくないものだけ共有を外せるようにしたい。この仕組み1本で、ギアもキャンプも料理も、そろえたい。

決まりは、1行になります。

見えるもの=「全体がオン」かつ「その1件で外していない」

種類ごとに違う切り替え方を覚えなくて済みます。作る側も、同じ形を3回作るだけです。今回は、最初の1つ(ギア)を作りました。

アカウントの画面の「共有」。ギア:共有しています。説明の文の下に、オンになったスイッチ「ギアを共有する」。その下に「ほかの人からの見え方を見る」「みんなの共有を見る」のリンク

アカウントの画面の「共有」(架空のデータ)

オンにするときは、確認を出します。「これから登録するギアも、共有されます」を、ここで伝えるためです。

確認のダイアログ。見出し「ギアを共有しますか?」。本文に、見えるようになる項目と、これから登録するギアも共有されること、見せたくないギアは編集でオフにできることが書いてある。ボタンは「やめる」と「ギアを共有する」

オンにするときだけ、確認が出る

見えるもの

共有にすると見えるのは、「所有」のギアの、次の6つです。

  • 製品名、メーカー、カテゴリ
  • 画像
  • おすすめ度、おすすめ理由

「欲しい」のギアは、出しません。まだ持っていないものです。どのコンテナに入れているか、どのプランで持っていくかも、出しません。

名前は、表示名(ニックネーム)で出します。Google の名前は、本名のことが多いので、使いません。表示名を決めていない人は、共有をオンにできないようにしました。


ほかの人のデータを読む場所を、1つにする

ハコヅミのデータベースの問い合わせには、今まで、1つの決まりがありました。

どの問い合わせも、自分の user_id で絞る。

これで、ほかの人のデータは、読めません。セカンドオピニオンのレビューでも、「ほかの人のデータに届く方法は、見つからなかった」と確かめてもらったところです。

共有は、この決まりの、はじめての例外です。ほかの人のギアを、読みます。

こわいのは、例外が、じわじわ広がることです。今ある「自分のギアを読む関数」に、「共有されていれば、ほかの人のも読む」という条件を足す。そういう作り方をすると、条件を1つ付け忘れただけで、共有していないギアが見えてしまいます。

そこで、読む場所を、1つのファイルに絞りました。

  • ほかの人のものを読む関数は、このファイルにだけ置く
  • どの関数にも、同じ2つの条件を付ける。「共有が見える人か」「共有されているギアか」
  • 条件は、1か所で定義して、全部の関数で使い回す
  • 読む列も、見せると決めた6つだけ。コンテナの列は、そもそも読まない

「見せない」のではなく、「読まない」。画面に出さないようにするだけだと、いつか、うっかり出します。

「いない」と「見せていない」を、同じにする

共有していない人のページを開くと、「ページが見つかりません」になります。そのとき、次の4つは、どれも同じ画面です。

  • 共有をオンにしていない人
  • 凍結された人
  • 表示名のない人
  • そもそも、いない id

「この人は、いるけれど、共有していない」と分かるだけでも、情報です。区別できないようにしました。

やめたら、すぐ見えなくなる

共有をオフにしたら、すぐに見えなくなる。これは、約束として、利用規約にも書きます。

気をつけたのは、画像です。自分のギアの画像は、ブラウザに長く覚えさせています(表示が速くなるので)。同じ設定のまま、ほかの人に配ると、共有をやめたあとも、相手のブラウザに残った画像が、しばらく出続けます。

ほかの人に配る画像は、入口を別にして、ブラウザに覚えさせない設定にしました。開くたびに、「まだ共有されているか」を確かめます。


スイッチの形を、3回変える

ここからは、受入の確認で直した話です。共有の切り替えの形を、3回変えました。

1回目:ボタンとチェックボックス

最初に作ったのは、こういう形でした。

  • 全体:「ギアを共有する」のボタン。押すとオンになり、ボタンが「ギアの共有をやめる」に変わる
  • 1件ごと:ギアの編集の一番下に、チェックボックス

動きとしては、まちがっていません。画面を見せると、返ってきたのは、一言でした。

全体の共有も個別の共有も、トグルボタンでの ON/OFF にして。

最初に頼んだ文に、「トグルボタン」と書いてありました。Claude Code は、それを「切り替えられるもの」と受け取って、ハコヅミに今あった部品(ボタンとチェックボックス)で作っていました。わたしが思い浮かべていたのは、スマホの設定の画面にある、あの丸いつまみのスイッチです。

オン・オフの2つの状態を持つものは、スイッチのほうが、今どちらなのかが一目で分かります。「共有する」というボタンは、押す前の状態(共有していない)を、言葉の裏から読み取らないといけません。

スイッチの部品を、1つ足しました。中身はチェックボックスで、見た目だけを変えています。

2回目:全体がオフなのに、1件ごとがオン

スイッチにして、開発環境で触ると、次の「あれ?」が出ました。

アカウントで「ギアを共有する」が OFF になっているのに、個別のギアではトグルが ON になっているのが分かりづらい。

1件ごとのスイッチは、「このギアを外すかどうか」の印です。初めは、どのギアも「外していない」なので、オンで出ます。全体がオフなら、どのギアも共有されていませんが、スイッチは、オンに見えます。

データの持ち方としては、正しい。画面としては、うそをついているように見えます。

わたしの案は、こうでした。

全体が OFF のときは、個別のトグルは自動的に OFF にする。全体を ON にしたら、個別のトグルも自動的に ON にする。

Claude Code は、半分に賛成して、半分に反対しました。

  • 賛成:全体がオフのあいだは、1件ごとのスイッチを、オフで出して、押せなくする
  • 反対:全体をオンにしたときに、全部をオンに戻すのは、やめたい

反対の理由は、こうです。

見せたくなくて外したギアが、オン・オフを1往復しただけで、また見えるようになる。

たとえば、もらいもののランタンを、共有から外していたとします。しばらく共有をやめて、また始める。そのとき、外したはずのランタンが、何も言わずに、見える側に戻っています。

本人が「見せない」と決めたものは、本人が変えるまで、そのままにする。こちらを採りました。

3回目:どれを外したかが、見えない

「オフで出して、押せなくする」で作り直して、もう一度触りました。今度は、別のことが気になりました。

個別で ON/OFF していたものは、全体の共有を OFF にした場合でも、ON/OFF の設定はそのまま見えて、かつ disable にしたほうがいいのでは?

全部がオフに見えると、どのギアを外してあったのかが、分かりません。全体をオンにするまで、確かめる手段がなくなります。

結局、決めてあるオン・オフのまま出して、押せなくする形になりました。オンに見えても、今は共有されていない。それは、スイッチの下の文で伝えます。

ギアの編集の一番下。薄い色のオンのスイッチ「このギアを共有する」。その下に「今は、どのギアも共有されていません。アカウントの画面で「ギアを共有する」をオンにすると、この設定で共有され、切り替えられるようになります。」

全体がオフのあいだ。決めてあるとおりに出るが、押せない

全体がオフのあいだの、1件ごとのスイッチ 困ったこと
1回目 オンで出て、押せる 共有されていないのに、オンに見える
2回目 オフで出て、押せない どれを外してあったかが、見えない
3回目 決めてあるとおりに出て、押せない。下に、今は共有されていないと書く —

3回目の形は、1回目に、だいぶ近いです。違うのは、「押せない」ことと、「下の文」だけ。

遠回りに見えますが、1回目の時点では、何が足りないのかが、分かっていませんでした。2回目で「全部オフ」を触ってみて、はじめて、「設定は見えていてほしい」と気づけました。画面は、触ってみないと分からない。何度も書いていることですが、今回もそうでした。


見たいものが、同時に見えない

ギアの共有を受入して、次(通報)に進もうとしたところで、気づきました。

共有のページは、自分のギアの一覧と同じく、リストとカードを切り替えられます。

「やまもり さんのギア」のページ。ギア 3 件。カテゴリ「キッチン」「テント」ごとに、ギアの名前、メーカーの札、おすすめ度の星、おすすめ理由が並ぶ。おすすめ理由は2行で切れている

ほかの人から見た、共有のページ(リスト表示)

ほかの人のギアで、見たいものは、3つです。画像、おすすめ度、おすすめ理由。

画像 おすすめ度 おすすめ理由
リスト表示 見えない 見える 見える
カード表示 見える 見える 見えない

3つを、同時に見る手段が、ありませんでした。

自分のギアなら、困りません。編集の画面を開けば、全部見えます。ほかの人のギアには、編集の画面がありません。自分の一覧と同じ形を、そのまま持ってきたので、「開いて見る」先がないことに、気づいていませんでした。

1件ごとの、詳細のページを足しました。

ギアの詳細のページ。小さく「やまもり さんのギア」、その下に大きく「シングルバーナー ST」。画像、メーカーの札、カテゴリ、おすすめ度の星4つ、おすすめ理由の全文。一番下に「やまもり さんのギア一覧へ」と「このギアを通報する」

ギアの詳細。画像・おすすめ度・おすすめ理由が、1つの画面に並ぶ(画像は、絵で代用)

ダイアログ(重ねて出す枠)ではなく、ページにしました。スマホの「戻る」で一覧に戻れること。そして、このあと作る「このギアを、自分の『欲しい』に入れる」と、通報のボタンの、置き場所になることが理由です。

順番も、入れ替えました。通報より先に、詳細のページを作ります。通報のボタンをどこに置くかが、このページで決まるからです。


通報がないうちは、出さない

ギアの共有は、10月12日に、開発環境で受入が済みました。でも、本番には出していません。

共有を考え始めたときに、決めていたことがあります。

通報と、管理者が共有を止める手段なしでは、共有を出さない。

ほかの人に見えるものができると、問題のあるものが、共有されるかもしれません。メーカーのサイトの写真を、そのまま使ったギア。関係のない宣伝を書いた、おすすめ理由。

そのときに、知らせてもらう手段と、止める手段が要ります。「問題が起きてから作る」では、起きた日に、何もできません。

通報

共有のページと、ギアの詳細の一番下に、通報のリンクを置きました。

通報のページ。通報する相手「やまもり さん」、ギア「シングルバーナー ST」。説明の文。理由は「権利を侵している」「不適切な内容」「その他」から選ぶ。説明の欄(必須、500 文字まで)。「通報を送る」のボタン

通報のページ

決めたことは、こうです。

  • 通報した人に、結果は知らせない
  • 通報された人に、だれが通報したかは、伝えない
  • 通報された人には、通報があったことも、知らせない
  • 自分の共有は、通報できない
  • 説明は、必ず書いてもらう

説明を必須にしたのは、理由を選んだだけでは、何が問題なのかを、確かめられないからです。

管理画面

管理画面に、通報の一覧を足しました。

管理画面の「通報」。未対応 1 件。日付、理由の札「権利」、通報された人のメールアドレス、説明の文、「通報されたギアを開く」のリンク、「対応した」のボタン

管理画面の、通報の一覧

通報した人は、管理画面にも出しません。データベースから、読んでもいません。

ハコヅミの管理画面には、「管理者に見えるのは、一覧と件数まで」という決まりがあります。ほかの人のギアの名前やメモは、管理者にも見えません。

通報の中身を確かめるときは、どうするか。「通報されたギアを開く」のリンクから、共有のページを、ほかの利用者と同じように開きます。共有されているものは、もともと、ログインしている人なら誰でも見られるものです。管理者だけに見える裏口は、作っていません。

凍結とは別に、「共有を止める」

問題のある共有を見つけたとき、管理者にできることは、今までは「凍結」だけでした。凍結すると、その人は、ハコヅミを何も使えなくなります。

写真を1枚、まちがって共有した人から、持ち物チェックまで取り上げるのは、やりすぎです。

軽い手段を、1つ足しました。「共有を止める」です。

管理画面のユーザーのカード。メールアドレス、「フリー」「共有中」の札、登録した日、件数。右下に「共有を止める」と「凍結する」のボタン

ユーザーのカード。「凍結する」の上に、「共有を止める」

凍結 共有を止める
ほかの人から 見えない 見えない
本人が使えるもの 何も使えない 共有のほかは、今までどおり
データ 消えない 消えない。共有の設定も残る
解いたとき もとどおり もとの設定のまま、また見える

止められた人のアカウントの画面には、こう出ます。

アカウントの画面の「共有」。赤い枠の中に「運営者が、あなたの共有を止めています」。今はほかの利用者から見えず、オンにもできないこと、登録した内容と共有の設定は残っていること、ほかの機能は使えること、心当たりがないときはお問い合わせへ、と書いてある。スイッチは出ていない

止められた人の、アカウントの画面

何が止まっていて、何が残っているのか。何は今までどおり使えるのか。心当たりがないときは、どこに言えばよいのか。止められた側が、いちばん知りたいことを書きました。


「見えません」と書いた文を、全部直す

共有を出すと、今まで書いてきた文が、そのままでは、うそになります。

場所 今までの文
紹介のページ 登録した内容は、ほかの利用者には見えません
使い方 見えません。ほかの利用者には、見えない作りになっています。
使い方 表示名を決められます。今は、ほかの人には見えません。
利用規約 (いまは、ほかの人に公開する機能はありません。)

機能と一緒に直さないと、「見えません」と書いてあるのに、見える。いちばん、やってはいけない形です。

通報と同じく、文の直しも、共有と一緒に本番に出すと決めていました。

利用規約とプライバシーポリシー

利用規約には、次のことを足しました。

  • 共有にすると、何が、誰に見えるか
  • 自分に権利のない画像や文を、共有にしないこと
  • 通報のこと、運営者が共有を止めることがあること(新しい条「通報と、共有の停止」)

プライバシーポリシーには、新しい条を1つ足しました。「共有にすると、ほかの利用者に見えるもの」。見えるものと、見えないものを、両方書きます。

見えないものを書くのは、読む人が、そこを知りたいからです。「共有にしたら、メールアドレスも出るのでは」「キャンプの記録も見えるのでは」。出ないものは、出ないと書いておきます。

文と実装を、1つずつ突き合わせる

規約やポリシーに書いたことは、約束です。書いたとおりに、動いていないといけません。

以前のレビューで、「料理が、規約のどこにも書かれていなかった」ということがありました。文と実装は、放っておくと、ずれます。

今回は、PR の本文に、突き合わせの表を作ってもらいました。一部を抜き出します。

文に書いたこと 実装
見えるもの:製品名・メーカー・カテゴリ・画像・おすすめ度・おすすめ理由 共有の問い合わせが読む列は、この6つと id だけ
見えないもの:メールアドレス、Google の名前 共有の問い合わせは、どれも読まない
オフにすると、すぐに見えなくなる 開くたびに、条件を確かめる。画像は、ブラウザに覚えさせない
管理の画面の通報に、通報した人は出ない 通報の一覧の問い合わせが、通報した人の列を読まない
退会すると、した通報も、受けた通報も、すぐに消える 退会の処理が、両方の向きで消す

全部で 16 行です。「読まない」「消す」と書いたものは、それを確かめる自動テストも、横に並べてあります。

テスタは、今の規約に同意して、ログインしています。なので、改定したことは、お知らせの一番上に、固定して出しました。

法律の専門家の確認は、受けていません。受けていないことは、隠さずに、Issue と PR に書いてあります。


Issue の本文を、空で上書きした

最後に、失敗の話です。Claude Code の失敗ですが、仕組みの話なので、書いておきます。

ハコヅミでは、わたしが「受入 OK」と言うと、Claude Code が、GitHub の Issue の受入条件に、チェックを付けます。やり方は、こうです。

  1. Issue の本文を読み出して、ファイルに保存する
  2. ファイルの中の「未チェック」を「チェック済み」に書き換える
  3. ファイルの中身で、Issue の本文を上書きする

文の直しの Issue で、1 の読み出しが、なぜか空で返りました。空のファイルを書き換えても、空のままです。3 で、Issue の本文が、空になりました。

Claude Code は、チェックの数を数えていたので、すぐに気づきました(「7 個のはずが、0 個」)。GitHub は、Issue の編集の履歴を持っています。そこから直前の本文を取り出して、戻しました。ほかの Issue が無事なことも、確かめています。

読み出しがなぜ空だったのかは、分かっていません。分かっていないので、「また起きる」前提で、手順のほうを変えました。

  • 書き戻す前に、中身が空でないこと、あるはずの見出しがあることを確かめる
  • 確かめに通らなければ、上書きしない

「読んで、変えて、書き戻す」は、読むところで失敗すると、書くところで壊します。書く前に、読めたものが、もっともらしいかを見る。前回の「マイグレーションは、データを入れて試す」と、根っこは同じです。うまくいく場合だけを通していると、うまくいかなかったときに、何が起きるかを知らないままになります。

今回は、履歴があったので、戻せました。戻せたのは、運がよかったのではなく、GitHub が履歴を残してくれていたからです。自分で作るものにも、同じ備えが要る、と思いました。


おわりに

  • 聞いてから作るつもりのものも、待つ時間が長いなら、作ってから聞く
  • 種類ごとに違う決まりは、1本にそろえられないかを、作る前に考える
  • 例外(ほかの人のデータを読む)は、置き場所を1つに絞る。「見せない」ではなく「読まない」
  • 「いない」と「見せていない」を、区別できないようにする
  • 言葉(トグル)は、同じものを思い浮かべているとは限らない。画面で確かめる
  • 本人が「見せない」と決めたものは、本人が変えるまで、そのままにする
  • 自分の一覧と同じ形を持ってくると、「開いて見る先がない」ことに気づきにくい
  • 止める手段は、問題が起きる前に作る。重い手段(凍結)しかないなら、軽い手段を足す
  • 機能を変えたら、それについて書いた文を、全部探して直す。書いたことは、実装と1つずつ突き合わせる
  • 「読んで、変えて、書き戻す」は、書く前に、読めたものを確かめる

共有は、まだギアだけです。次は、行き終わったキャンプ、その次は料理。同じ仕組みで、足していきます。

← トップページに戻る