alba-inertia について
Inertia Rails で Alba シリアライザーと Typelizer を使うためのスキルガイドです。Inertia の props を再利用可能なリソースとして構成し、TypeScript 型を生成する開発者向けです。
主な機能
- 01エンティティ、ページ、共有 props のリソース定義
- 02Alba による Inertia props のシリアライズ
- 03Typelizer による TypeScript 型生成
- 04defer や optional などの Inertia prop オプション
- 05規約に基づくコントローラー描画
活用シーン
- 01型のない as_json props を構造化リソースに置き換え
- 02複数ページでエンティティのデータ形状を共有
- 03シリアライズした props の TypeScript 型を生成
- 04遅延データや任意データの Inertia prop 動作を設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ inertia-rails/ skills --skill alba-inertiaインストール後、Claude Code で/alba-inertiaを入力して読み込まれたか確認します。
同梱ファイルreferences/prop-options.md
詳細
Inertia Rails 向け Alba + Typelizer
必要なもの:Gemfile に alba、typelizer、alba-inertia の各 gem。
Inertia の props 用 Alba シリアライザーで、TypeScript の型を自動生成します。
as_json(only: [...]) を、構造化された型安全なリソースに置き換えます。
リソースを作成する前に確認してください:
- 再利用可能なデータ構造(ユーザー、コースなど)ですか? → エンティティリソース(
UserResource)—複数のページで共有します - ページ固有の props のまとまりですか? → ページリソース(
UsersIndexResource)—コントローラーのアクションごとに作成します - グローバルデータ(認証、通知など)ですか? → 共有 props リソース(
SharedPropsResource)
絶対に行わないでください:
- Alba の設定後に
as_jsonを使うこと — 型生成を迂回し、型のない props が作成されます - リソース名がモデル名と異なる場合に
typelize_fromを省略すること — Typelizer がカラムの型を推論できず、unknownを生成します declare moduleの拡張をserializers/index.tsに置くこと — Typelizer が生成する型はserializers/index.tsに、手動で設定する InertiaConfig はglobals.d.tsに置きます
セットアップ
ApplicationResource(すべてのリソースが継承します)
# app/resources/application_resource.rb
class ApplicationResource
include Alba::Resource
helper Typelizer::DSL # enables typelize, typelize_from
helper Alba::Inertia::Resource # enables inertia: option on attributes
include Rails.application.routes.url_helpers
end
コントローラーとの連携
# app/controllers/inertia_controller.rb
class InertiaController < ApplicationController
include Alba::Inertia::Controller
inertia_share { SharedPropsResource.new(self).to_inertia }
end
リソースの種類
エンティティリソース(再利用可能なデータ構造)
# app/resources/user_resource.rb
class UserResource < ApplicationResource
typelize_from User # needed when resource name doesn't match model
attributes :id, :name, :email
typelize :string?
attribute :avatar_url do |user|
user.avatar.attached? ? rails_blob_path(user.avatar, only_path: true) : nil
end
end
ページリソース(ページ固有の props)
# app/resources/users/index_resource.rb
# Naming convention: {Controller}{Action}Resource
class UsersIndexResource < ApplicationResource
has_many :users, resource: UserResource
typelize :string
attribute :search do |obj, _|
obj.params.dig(:filters, :search)
end
end
共有 props リソース
Rails の Current 属性(例:Current.user)を設定する必要があります —
CurrentAttributes を参照してください。
# app/resources/shared_props_resource.rb
class SharedPropsResource < ApplicationResource
one :auth, source: proc { Current }
attribute :unread_messages_count, inertia: { always: true } do
Current.user&.unread_count || 0
end
has_many :live_now, resource: LiveSessionsResource,
inertia: { once: { expires_in: 5.minutes } }
end
規約に基づくレンダリング
Alba::Inertia::Controller を使用すると、インスタンス変数が自動的にシリアライズされます。
class UsersController < InertiaController
def index
@users = User.all # auto-serialized via UserResource
@filters = filter_params # plain data passed through
# Auto-detects UsersIndexResource
end
def show
@user = User.find(params[:id])
# Auto-detects UsersShowResource
end
end
Typelizer と型生成
typelize_from は、カラムの型を推論する元となるモデルを Typelizer に指定します — リソース名がモデル名と一致しない場合に必要です。計算属性については、型を明示的に宣言してください。
class AuthorResource < ApplicationResource
typelize_from User
attributes :id, :name, :email
typelize :string? # next attribute is string | undefined
attribute :avatar_url do |user|
rails_storage_proxy_path(user.avatar) if user.avatar.attached?
end
typelize filters: "{category: number}" # inline TS type
end
Rails サーバーの実行時に型が自動生成されます。手動で生成する場合:bin/rake typelizer:generate。
Alba での Inertia Prop オプション
属性や関連付けの inertia: オプションは、InertiaRails の prop 型に対応します。
attribute :stats, inertia: :defer # InertiaRails.defer
has_many :users, inertia: :optional # InertiaRails.optional
has_many :countries, inertia: :once # InertiaRails.once
has_many :items, inertia: { merge: true } # InertiaRails.merge
attribute :csrf, inertia: { always: true } # InertiaRails.always
必須 — グループ化された defer、match_on を指定した merge、scroll props、または複数のオプションの組み合わせを使用する場合は、ファイル全体を読んでください:
references/prop-options.md(約60行)— すべての inertia: オプションのバリエーションと、代替構文 inertia_prop の完全な構文を説明しています。
基本的な inertia: :defer、inertia: :optional、または
inertia: :once には読み込まないでください — 上記の簡略構文で十分です。
トラブルシューティング
| 症状 | 原因 | 対処方法 |
|---|---|---|
TypeScript の型がすべて unknown になる | typelize_from が指定されていない | リソース名がモデル名と一致しない場合は、typelize_from ModelName を追加します |
inertia: オプションが反映されない | ヘルパーが不足している | ApplicationResource に helper Alba::Inertia::Resource があることを確認します |
| 型が再生成されない | サーバーが実行されていない | Typelizer がファイルを監視するのは開発時のみです。bin/rake typelizer:generate を手動で実行します |
typelize に対する NoMethodError | ヘルパーが不足している | ApplicationResource に helper Typelizer::DSL があることを確認します |
| 規約に基づくレンダリングで誤ったリソースが選ばれる | 命名の不一致 | リソース名は {Controller}{Action}Resource にする必要があります(例:UsersController#index には UsersIndexResource) |
to_inertia が未定義 | include が不足している | コントローラーに include Alba::Inertia::Controller が必要です |
関連スキル
- Prop の型 →
inertia-rails-controllers(defer、once、merge、scroll) - TypeScript の設定 →
inertia-rails-typescript(globals.d.tsの InertiaConfig)