mcpField
A
alba-inertia

alba-inertia

github.com/inertia-rails开发70378 次安装37 周前更新
代码仓库

关于 alba-inertia

这项技能介绍如何在 Inertia Rails 中使用 Alba 序列化器和 Typelizer。它帮助开发者将 Inertia props 组织为可复用资源,并据此生成 TypeScript 类型。

主要功能

  1. 01定义实体、页面和共享 props 资源
  2. 02使用 Alba 序列化 Inertia props
  3. 03通过 Typelizer 生成 TypeScript 类型
  4. 04支持 defer、optional 等 Inertia prop 选项
  5. 05提供基于约定的控制器渲染

适用场景

  1. 01用结构化资源替代无类型的 as_json props
  2. 02在多个页面复用实体数据结构
  3. 03为序列化后的 props 生成 TypeScript 类型
  4. 04为延迟或可选数据设置 Inertia prop 行为

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/inertia-rails/skills --skill alba-inertia

安装后在 Claude Code 中输入/alba-inertia确认已加载。

附带文件references/prop-options.md

详细介绍

Alba + Typelizer 用于 Inertia Rails

要求:Gemfile 中包含 alba、typelizer、alba-inertia gems。

用于 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、滚动 props 或组合多个选项时,请阅读整个文件: references/prop-options.md(约 60 行)——包含所有 inertia: 选项变体及 inertia_prop 备用语法的完整语法说明。

基本的 inertia: :defer、inertia: :optional 或 inertia: :once 无需加载——以上简写已足够。

故障排除

症状原因修复方法
TypeScript 类型全部为 unknown缺少 typelize_from资源名称与模型名称不同时,添加 typelize_from ModelName
inertia: 选项不起作用缺少 helper确认 ApplicationResource 中包含 helper Alba::Inertia::Resource
类型未重新生成服务器未运行Typelizer 仅在开发环境中监视文件。手动运行 bin/rake typelizer:generate
typelize 出现 NoMethodError缺少 helper确认 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)

评论

支持 Markdown