Rails consoleで投入したデータが画面に反映されない原因調査メモ:--sandboxモード

現象

stagingのRailsコンソールから新しいレコードを作って、画面に反映されるかを確認する作業をしていた。

request = SomeResource.new(...)
request.save_by!(user)
# => true

コンソール上では count も増えており、find_by でも作成したレコードが取得できる。一方、ブラウザで一覧画面を開くと、作成したはずのレコードがリストに含まれない。

原因

rails console--sandbox 付きで起動していた。

--sandbox モードは、コンソールでの操作を1つのトランザクションに包んで終了時にROLLBACKする。書き込んだつもりのレコードは最初からCOMMITされていないため、別接続(ブラウザ)からは見えない。

console内では find_bycount も同一トランザクションから読んでいるため、書き込んだ直後のレコードが普通に取得できる。このため、console内では保存できているように見えるが、別接続からは見えない、という状態になる。

調査の経緯

Claudeから出てきた仮説はキャッシュ系に偏っていた。

  1. ブラウザ・CDNのレスポンスキャッシュ
  2. read replicaのレプリケーション遅延
  3. ETag・Cache-Control ヘッダ
  4. ブラウザ側の永続キャッシュ

いずれも該当しなかった。

自分側の仮説は「rails cでの確認方法がview側のロジックと違うのではないか」というものだった。Claudeで controller#index をconsole上でトレースすると、結果は毎回「該当レコードを含む」。一方、ブラウザの一覧では「含まない」。同じコードを同じDBに対して実行しているのに結果が違う、という状態が残った。

結局、Claudeのキャッシュ系仮説も、自分のviewロジック差異仮説も、いずれも外していた。

最終的に、コンソールが --sandbox で起動していたことに気づいた。書き込みは最初からCOMMITされておらず、controllerとconsoleの差ではなく、console側のトランザクションがそもそも残らない設定で起動していた、というだけのことだった。

チェックリスト

「console内では見えるのに別接続からは見えない」という現象が出ているときは、sandboxの可能性が高い。同様の現象は他のケースでも起きるので、合わせてチェック対象にしておく。

  • console内で取得できるレコードが、別接続(ブラウザ・別console・psql等)から見えない → まず --sandbox を疑う
  • consoleの起動メッセージとプロンプトの (sandbox) を確認する
  • 同様のケース:別環境への接続、別tenant、別user権限、未commitのトランザクション
  • console内の自分のreadは保存確認にならない。同一トランザクション内では見えて当たり前なので、保存検証は別セッションから行う

まとめ

  • rails console --sandbox で書き込むと、console内では見えるが別接続から見えない
  • 「console内で見える / 別接続で見えない」という現象を観測したら、まず --sandbox を疑う
  • consoleの起動メッセージとプロンプトの (sandbox) で判別できる
  • 手元のローカル情報(プロンプト、起動方法、環境変数)はAIエージェントからは見えない

Railsでschema.rbのカラム順ずれを直す方法

起きること

rails db:migrate した後に rails db:schema:dump すると、コミット済みの schema.rb と差分が出ることがある。

 create_table "users", force: :cascade do |t|
   t.string "email", null: false
-  t.string "nickname"
   t.string "name", null: false
+  t.string "nickname"
   t.datetime "created_at", null: false

変わったのはカラムの並び順だけ。機能的には問題ないが、PRでの差分レビュー時にノイズになる。

なぜカラム順がずれるのか

RDBMSは一般的に カラムの物理的な順序を変更できない。そして add_column は常にテーブルの末尾にカラムを追加する。

この性質により、以下のケースでずれが発生する。

1. ブランチ切り替えによるマイグレーション実行順の違い

チーム開発で最もよくあるケース。

開発者Xがmigration Aを、開発者Yがmigration Bをそれぞれ別ブランチで作成し、両方がmainにマージされたとする。

  • 開発者X: Aを先に実行 → mainをpullしてBを実行 → col_A, col_B の順
  • 開発者Y: Bを先に実行 → mainをpullしてAを実行 → col_B, col_A の順

開発者Xが schema.rb をコミットすると col_A, col_B の順になるが、開発者Yが db:schema:dump すると col_B, col_A の順で出力される。

2. マイグレーションのロールバック→再実行

開発中に普通にやる操作で起きる。

ブランチで add_column :users, :nickname を実行した後、rails db:rollback してマイグレーションを修正、再度 rails db:migrate すると、nickname カラムはテーブル末尾に移動する。

ロールバック前に中間あたりにあったカラムが、再実行後は末尾に来るためずれが生じる。

解決方法: データを保持したままDBを再作成

自分のマイグレーションによる構造変更とカラム順のノイズが混在すると、本来の変更が埋もれてレビューしづらい。

ローカルDBのカラム順をリセットしてから rails db:schema:dump をやり直すと、きれいな差分になる。

DBを schema.rb から再作成すれば、定義順どおりにカラムが作られる。データはダンプ・リストアで退避・復元する。

手順(PostgreSQLの例)

# 1. データだけダンプ(スキーマは含まない)
pg_dump --data-only --format=custom -f /tmp/db_data_backup.dump myapp_development

# 2. DB再作成(schema.rbのカラム順で作られる)
rails db:drop db:create db:schema:load

# 3. データをリストア(--disable-triggers でFK制約を一時無効化)
pg_restore --data-only --disable-triggers -d myapp_development /tmp/db_data_backup.dump

注意点

ar_internal_metadata / schema_migrations の重複エラー

pg_restore: error: COPY failed for table "ar_internal_metadata": ERROR:  duplicate key value violates unique constraint
pg_restore: error: COPY failed for table "schema_migrations": ERROR:  duplicate key value violates unique constraint
pg_restore: warning: errors ignored on restore: 2

この2テーブルは db:schema:load 時にRailsが自動作成するため重複する。アプリのデータには影響しないので無視してOK。

循環FK制約の警告

pg_dump: warning: there are circular foreign-key constraints on this table:
pg_dump:   some_table
pg_dump: You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints.

pg_dump 時にこの警告が出ることがあるが、リストア時に --disable-triggers を付けているので問題ない。

所要時間

ダンプファイルのサイズで目安がつく。開発環境のDBが数十MB程度なら数秒で完了する。

ls -lh /tmp/db_data_backup.dump

まとめ

  • RDBMSはカラムの物理順を変更できないため、マイグレーションの実行順が人によって異なるとカラム順がずれる
  • チーム開発やマイグレーションのロールバック→再実行で日常的に発生する
  • pg_dump --data-onlydb:schema:loadpg_restore --data-only でデータを保持したままリセットできる

Devise認証失敗の原因調査メモ:インデックス破損

概要

Rails + Deviseを使用している開発環境で、突然ログインできなくなる事象が発生。
エラーメッセージは「メールアドレスまたはパスワードが違います」。
パスワードを再設定しても改善せず、調査の結果、インデックス破損が原因だった。

対応内容をメモしておく。


現象

  1. Deviseのログイン画面で、認証エラーが発生。
    表示されるメッセージは「メールアドレスまたはパスワードが違います」。

  2. Railsコンソールで対象ユーザーのパスワードを更新。

     user = AdminUser.find_by(email: 'user@example.com')
     user.update!(password: 'newpassword123', password_confirmation: 'newpassword123')
    

    更新は正常に完了。

  3. パスワード検証を実施。

     user.valid_password?('newpassword123')
     # => true
    

    パスワード検証は成功。
    認証情報には問題ないことを確認。

  4. find_byで対象ユーザーを検索。

     AdminUser.find_by(email: 'user@example.com')
     # => nil
    

    検索できない。

  5. pluckでテーブルに存在するemail一覧を確認。

     AdminUser.pluck(:email)
     # => ["user@example.com", ...]
    

    対象のメールアドレスは存在している。
    データは存在しているように見えるが、検索できない矛盾した状態。


調査

DBコンソール(psql)から直接クエリを実行。

SELECT * FROM admin_users WHERE email = 'user@example.com';

結果、0行。

また、メールアドレスのバイト列を確認。

user = AdminUser.find_by(name: '任意の名前')
user.email.bytes

不要な不可視文字(スペース、タブ、改行、ヌル文字など)が含まれていないことを確認。
データの破損や文字列汚染の可能性は排除できた。

ここまでの調査から、インデックス破損の可能性が高いと判断。


対応

該当インデックスを一度削除し、再作成。

DROP INDEX index_admin_users_on_email;
CREATE UNIQUE INDEX index_admin_users_on_email ON admin_users (email);

再作成後、

AdminUser.find_by(email: 'user@example.com')

が正常にレコードを返すようになり、Devise認証も復旧。


まとめ

  • Deviseの認証エラーでも、パスワード問題とは限らない
  • データが存在するのにfind_byできない場合、インデックス破損を疑う
  • PostgreSQLではインデックス破損により検索が失敗することがある
  • DROP INDEX → CREATE INDEXでインデックス再作成すれば復旧可能

ぼくたちは習慣で、できている

要約

才能は与えられるものではなく、努力を続けた後に「作られるもの」
その努力は、習慣にしてしまえば、歯をくしばることなく継続できる
その習慣は学べるものである

才能や努力は限られた人にしかできないものではなく、工夫次第で身につけられるものである。

本書の構成は次のとおり

  1. 意思力は、生まれつき決まってる?
  2. 習慣とは何か?
  3. 習慣を身につけるための50のステップ
  4. 僕たちは習慣で、できている

第1章「意思力は、生まれつき決まってる?」のまとめ

人には双極割引という性質がある。
目の前の報酬ほど大きく感じ、将来にある報酬や罰則は少なく見積もってしまう、というもの。
このために、好ましい習慣を身につけるのが難しい。
狩猟生活に適した仕組みではあったが、社会のルールが変わった現代においてはやっかいなもの。

マシュマロ・テストという有名な実験がある。
目の前のマシュマロを食べずに、20分待って2個のマシュマロを得た子供は、成人後、成績や人望に至るまであらゆる能力が高かった。

意思力は使うと減るというものではない。
使わなければ回復するというものではない。
ラーメンを食べたらポテチも食べてしまいダメおしのアイスまで食べてしまう。

意思力は感情に左右される
不安や自己否定感によって失われる。

やらないことで減る意思力もある
ジムに行けなかったときに不健康な食品に手を出してしまう
午前中ダラダラしている人は午後もずっとダラダラ過ごしてしまう
意思力を消耗させるマイナスの感情が「自己否定感」や「不安」だ。

一方で、意思力が必要な行動を取っても、自己肯定感を感じていれば意思力は減らない
喜びの感情は意思力を回復させる
楽しい気分ならマシュマロも待てる

人の脳には2つのシステムがある
感情的なホットなシステムと理性的なクールなシステムである。

不安を感じたり、ネガティブな感情を感じると、本能的なホットシステムが活性化する

マシュマロのことを考えながら待つように指示された子供たちは、短い時間しか待てなかった
一方、目の前から本物のマシュマロを取り去っただけで、子供たちはより長く待てるようになった

マシュマロを我慢するためには、そもそも誘惑されなければいい。
そのためには目の前の現実をどう捉えるかというクールシステムの「認知」の力が役に立つ。
この認知はコツを教えることで実践できるようになった。それは後から学べるスキルだということだ。

  • マシュマロを「丸くふっくらした雲」だと思うようにアドバイスすると2倍待つことができた
  • マシュマロを「本物ではない」と思うようにアドバイスすると平均18分待てるようになった


鍛えられるのは意思力ではなく、この認知力
意思力が強いと思われていた人は、誘惑に抵抗している時間がそもそも短かったということ

意思決定はコイントスのように不合理であり、
マシュマロを待てなかったのは、単にコインを投げる回数が多かったせいだ。
すると対策はコインを投げない=意識を呼び戻さないことになる

感想

習慣の実行で得られる報酬は、自己肯定感である。
それ以上は求めすぎないようにしたい。何かしら目に見える成果は、ついてきたらもうけもの。

なぜ自己肯定感が大切なのか。それは意志力を保つため。
不安や自己否定感が生まれると意志力が落ちる。
意志力が落ちてホットシステムが活性化すると、目の前の欲求を満たそうとしてしまう。
結果、身につけたい習慣が身につかなくなる。

不安とか努力とかネガティブな感情は持たなくて良い。
習慣を身につけるために、苦しむ必要はない。むしろ苦しんではいけない。

こんな自分でも意思力をコントロールできそうな勇気が湧いてきた。
そもそも意志力に必要なのは忍耐でない。「認知力」の使い方しだいで、習慣を身につけることができそうに思えてきた。

才能が無いという諦めはやめよう。
今からでも遅くはない。今が人生で一番若い日なのだから。

金持ちフリーランス 貧乏サラリーマン

本の紹介

要約

「お金持ちに搾取され続ける人生」から抜け出そう。

資本主義とは、ありていに言えば「お金がすべて」の世界。 資本主義の世界で悠々と生き続けるには、お金持ちになるしかない。 「いや、お金がすべてじゃない!」という考え方は搾取を食うことになる。

サラリーマンは最も稼げない業務形態 「使えない社員」の給与を「使える社員」が賄っているからである。

筆者は「フリーランスエンジニア」になっただけで、 働き方はほとんど変わっていないにもかかわらず、 収入が一気に3倍になったとのこと。

本書は資本主義の世界で、「貧乏人」から「お金持ち」への大逆転を画策する一冊。 人生逆転のカギは「知識投資」 次のような、お金持ちになるためのエッセンスが詰め込まれている - お金に対して持つべき意識 - お金の貯め方 - お金の稼ぎ方 - お金の使い方 - お金の増やし方

感想

頑張るほど「自腹」を切らされるサラリーマン

確かに仕事でしか使わないものなのに自腹で買わなければならない事態は多い

いきなりサラリーマンをやめろとは言わない 続けながら副業をはじめて、理不尽にとられていく税金をちょっとずつ減らしてみる

ふむ、それならやってみよう、という気になれる。

その責任感は「フリーランス」で生かすべき 中堅サラリーマンであれば誰でも、「サラリーマン時代と同じ働き方」を続けるだけで、無双できる。

そうなのか、勇気が湧いてきた

フリーランスに「リスク」なんてない。それなのに「お金」と「自由」の両方を手に入れることができる。

フリーランスになるのはメリットしか無いように思えてきた

影響力は「最強の資産」

影響力は今のところ全然無いな。 これまで意識してなかった。 これを機に影響力を高めていこう。

自己肯定感を上げる OUTPUT読書術

本の紹介

「読書によって、人は自己肯定感を高め、人生を好転させることができる」
これが本書で最も伝えたいメッセージ。

それを実現するためにいちばん重要なアクションが、
読んだ本を「アウトプット」すること

その方法論を詳細かつ具体的に示すことが本書の役割。

筆者がこの本にこめた思いは次の3点

  1. 人間の自己肯定感は、読書によってコントロール可能である
  2. 読書によって得た、筆者自身の最大の成功体験が、自己肯定感の回復
  3. 自己肯定感に悩み苦しんでいる人の力になりたい

なぜ「OUTPUT」読書術なのか?
答えは、「人間はOUTPUTをすることで、はじめて自分の人生に変化を起こせるから」

感想

本は、悩みやストレスを解消する万能薬

この観点は、今までの読んだ読書術本にはなかった気がする。

人間はOUTPUTをすることで、初めて自分の人生に変化を起こせる

なるほど、やってみよう。と思いこの記事を書いている。 これまでなかなかできなかったけど、 ゆるっとでもまずは書いてみることが大切なはず。

読書の目的を明確にすること

この本を読んだ目的は以下のとおり。

  • もっと発信したい
  • 自己肯定感を高めたい
  • 本をたくさん読んで、やりたいことを見つけたい

その先にあるのは「人生を楽しみたい」というのが究極の目的

何事も長く続けるうえで大切なことは「とにかく楽しむこと」 です。

読書も楽しむ。OUTPUTも楽しむ。そうなれるように無理をしないようにしよう。

思うように読書が進まなくてつらい。OUTPUTすることが苦しくなってしまった。そういった症状が出てきたら、まずはいったん立ち止まって深呼吸

辛くなるのであれば、「人生を楽しみたい」という究極の目的から逸れているわけで、本末転倒になる。
だから、辛くなったらやり方を見直さないといけない
英会話とか筋トレとか他の習慣も同様かも。

この言葉にこれから救われそう。
とてもやさしくてありがたい言葉。

どんな人におすすめか

  • 読書がなかなか続かない人
  • 自己肯定感を高めたい人

Work-Life Balance

I think people should spend at work less than 8 hours a day. People should spend with their families more than 3 hours a weekday. People should take breakfast and dinner with family.

It is easy for me to leave work early for family events. There are no time cards. If I produce results, it's ok to leave work early.

I don’t need to quit your job for my family. I can work from home. I can arrange work time. It's very good job for my family.