react-intersection-observerを使って初期描画を減らし高速化する May 15, 2025
データをリストで表示する。データ数が多く、単純なリスト描画をすると初期描画に時間がかかる。わけアリでcursorのようにデータを逐次取得するような状態ではない。フロントエンド側で調整する。
イメージ以下のような構造
<List>
{lists.map((item) => (
<Item item={item}/>
))}
< /List>
端的に言うと、ある要素が別の要素(通常はviewport)との交差状況の変化を非同期に監視できる。これを使うことで、必要なときに描画の処理をすればよくなるため、初期描画が最適化される。
useInViewを使う。遅延描画用のLazyItemコンポーネントを作る
export const LazyItem: React.FC = () => {
const [ref, inView] = useInView({
triggerOnce: true ,
rootMargin: "200px 0px" ,
});
return (
<div ref={ref}>
{inView ? <Item /> : <div style={{ height: "40px" }} />}
< /div>
);
};
描画対象じゃないときは少し高さを持たせ、後続のitemが描画されないようにしている。これを使うことで遅延描画が達成
データベースの世界のNULLは偽ではない May 13, 2025
Railsの世界に浸かっていると基本的なことを忘れる。戒めメモ
User.all.pluck( :type ).tally
=> {nil => 26 , "aaa" => 9 , "bbb" => 1 , "ccc" => 2 }
User.where. not ( type: "bbb" ).count
=> 11
この結果が直感的でなかった(nilも含まれると思っていた)けど、よく考えたらデータベースの世界では
3値論理 でNULL != falseだった。
User.where. not ( type: nil )
で何らかの値が入っているレコードが取れることを考えると、そこまで不思議ではなかった
ちなみにnilも含めたい場合はorを使う
User.where. not ( type: "bbb" ). or (User.where( type: nil ))
素のRails + PostgreSQL構成をdockerで管理するようにしたメモ May 9, 2025
個人開発の素のRails + PostgreSQLアプリがある。Redisを導入したくて、ついでにDocker管理するようにした。職場でDockerが使われているが、既に構築されたものをたまにメンテするぐらいで、一から作るのは初めてだったので新鮮だったメモ。
Dockerfileの作成 FROM ruby: 3.2 . 2 -slim-bookworm
## 必要なパッケージをインストール
RUN apt update -qq && apt install -y --no-install-recommends \
build-essential \
libpq-dev
# 作業ディレクトリを設定
WORKDIR /app
# GemfileとGemfile.lockをコピー
COPY Gemfile Gemfile.lock ./
# Bundlerをインストールし、依存関係をインストール
RUN gem install bundler: 2.6 . 8
RUN bundle install --jobs= $( nproc) -- retry = 3
# アプリケーションコードをコピー
COPY . .
# エントリーポイント
CMD [ "rails" , "server" , "-b" , "0.0.0.0" , "-p" , "3000" ]
# ポートを公開
EXPOSE 3000
いろいろなものを参考にしながら作成。古いアプリなのでRubyも古い。今度上げる。
docker-composeの作成 version: '3.9'
services:
db:
image: postgres: 16
environment:
POSTGRES_USER: XXX
POSTGRES_PASSWORD: XXX
POSTGRES_DB: XXX
DATABASE_HOST: db
volumes:
- db_data: /var/lib/postgresql/data
ports:
- "5432:5432"
web:
build: .
volumes:
- . :/app
ports:
- "3000:3000"
depends_on:
- db
environment:
RAILS_ENV: development
DATABASE_HOST: db
DATABASE_USERNAME: XXX
DATABASE_PASSWORD: XXX
DATABASE_NAME: XXX
REDIS_URL: redis: / /redis:6379/ 1
redis:
image: redis: 8
ports:
- "6379:6379"
volumes:
- redis_data: /data
volumes:
db_data:
redis_data:
DBに接続ができずにハマる。何度かPostgreSQLのユーザー名を変更したのと、その変更のキャッシュが残っていた関係で接続ができなくなった。イメージのビルドを明示的に指定することで解決。
docker-compose up --build
マイグレーションの実行 docker compose exec web rails db: migrate
データの移行 環境を作っただけでデータがない。これまでローカルのPostgreSQLに保持していたデータをコンテナで呼び出している
Docker Volume に移行する
pg_dump database_name > local_backup.sql
docker cp local_backup.sql db-container- name: /tmp/local_backup.sql
docker compose exec db psql -U postgres -d database_name -f /tmp/local_backup.sql
ぼんやり知っているつもりだったけど、実際に手を動かしてみると色々時間取られた
33歳になった May 7, 2025
昨日33歳になった。1年後の自分がゲラゲラ笑うかも知れないので、ぼんやり考えていることを雑に残す。
「年を取ると一年が早くなる」とよく言われるが、個人的にはそんなことはない気がする。一年が早くなるのは、おそらく年齢を重ねるごとにイベントごとが少なくなりがちだからだろう。ここ一年はいろいろなところに出かけたり、美味しいものを食べたりといった思い出がたくさんあるので、密度の濃い充実した一年を過ごせた気がする。これからもそういう思い出をたくさん作っていきたい。このあたりの考え方は
DIE WITH ZERO の影響を強く受けている。
プライベートは充実しているが、仕事はどうだろうか。社会人になって8年ちょっと、Webエンジニアになってもうすぐ6年になる。エンジニアとしてできることはたくさん増えてきたが、ここ最近はできることを淡々とやっている感覚があり成長実感が薄くなっている。いわゆるキャリアを考えるというやつか。
それでいうと、個人の能力を高めることはもちろん大切だけれど、チームとしてより高みを目指すことも大事だなとここ一年で強く思うようになった。一人で出来ることは限界があるが、チーム、組織ならもっといろいろなことが出来る。これを表現するのはマネジメントといった世界になるのだろうか。
そんなことを考えながら、お祝いですき焼きを食べた。めちゃくちゃ旨い。
group_by を group + array_agg で高速化する(PostgreSQL) April 28, 2025
こういうパフォーマンス改善もあるよメモ
ユーザーと記事があり、ユーザーは記事をお気に入りできる。お気に入りには種類がある。お気に入りの種類ごとに記事のidの配列を取得するような処理を考える。
{
"like_name_1" => [ 1 , 2 , 3 , 4 ],
"like_name_2" => [ 5 , 6 , 7 , 8 ],
}
最終的にはこんな感じのデータを取りたい
group_by を使う Like
.where( user_id: user.id)
.select( :name , :post_id )
.group_by(& :name )
.transform_values { |v| v.pluck( :post_id ) }
group_byでDBの結果を取得しtransform_values以降をRailsで処理することになる。数が多い場合はパフォーマンスが気になる
group + array_aggを使う NULLも含めてすべての入力値を収集して配列に格納します。
Like
.where( user_id: user.id)
.group( :name )
.select( :name , "array_agg(post_id) as post_ids" )
.to_h{ |g| [g.name, g.post_ids] }
こうすることでgroupの処理をDB側に寄せることができる。ただし、可読性の低下や、PostgreSQLに依存した実装になってしまうためそのあたりのデメリットは考慮すること。