alba-inertia

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Alba + Typelizer for Inertia Rails

用于Inertia Rails的Alba + Typelizer

Requires:
alba
,
typelizer
,
alba-inertia
gems in Gemfile.
Alba serializers for Inertia props with auto-generated TypeScript types. Replaces
as_json(only: [...])
with structured, type-safe resources.
Before creating a resource, ask:
  • Reusable data shape (user, course)? → Entity resource (
    UserResource
    ) — shared across pages
  • Page-specific props bundle? → Page resource (
    UsersIndexResource
    ) — one per controller action
  • Global data (auth, notifications)? → Shared props resource (
    SharedPropsResource
    )
NEVER:
  • Use
    as_json
    when Alba is set up — it bypasses type generation and creates untyped props
  • Skip
    typelize_from
    when resource name differs from model — Typelizer can't infer column types and generates
    unknown
  • Put
    declare module
    augmentations in
    serializers/index.ts
    — Typelizer-generated types go in
    serializers/index.ts
    , manual InertiaConfig goes in
    globals.d.ts
要求: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

Setup

配置步骤

ApplicationResource (all resources inherit from this)

ApplicationResource(所有资源都继承自该类)

ruby
undefined
ruby
undefined

app/resources/application_resource.rb

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
undefined
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
undefined

Controller Integration

控制器集成

ruby
undefined
ruby
undefined

app/controllers/inertia_controller.rb

app/controllers/inertia_controller.rb

class InertiaController < ApplicationController include Alba::Inertia::Controller
inertia_share { SharedPropsResource.new(self).to_inertia } end
undefined
class InertiaController < ApplicationController include Alba::Inertia::Controller
inertia_share { SharedPropsResource.new(self).to_inertia } end
undefined

Resource Types

资源类型

Entity Resource (reusable data shape)

实体资源(可复用的数据结构)

ruby
undefined
ruby
undefined

app/resources/user_resource.rb

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
undefined
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
undefined

Page Resource (page-specific props)

页面资源(页面专属props)

ruby
undefined
ruby
undefined

app/resources/users/index_resource.rb

app/resources/users/index_resource.rb

Naming convention: {Controller}{Action}Resource

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
undefined
class UsersIndexResource < ApplicationResource has_many :users, resource: UserResource
typelize :string attribute :search do |obj, _| obj.params.dig(:filters, :search) end end
undefined

Shared Props Resource

共享Props资源

Requires Rails
Current
attributes (e.g.,
Current.user
) to be configured — see CurrentAttributes.
ruby
undefined
需要配置Rails的
Current
属性(如
Current.user
)—— 详情请查看CurrentAttributes
ruby
undefined

app/resources/shared_props_resource.rb

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
undefined
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
undefined

Convention-Based Rendering

基于约定的渲染方式

With
Alba::Inertia::Controller
, instance variables auto-serialize:
ruby
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
集成
Alba::Inertia::Controller
后,实例变量会自动序列化:
ruby
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 + Type Generation

Typelizer + 类型生成

typelize_from
tells Typelizer which model to infer column types from — needed when resource name doesn't match model. For computed attributes, declare types explicitly:
ruby
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
Types auto-generate when Rails server runs. Manual:
bin/rake typelizer:generate
.
typelize_from
用于告知Typelizer要从哪个模型推断列类型——当资源名称与模型名称不一致时必须使用。对于计算属性,需显式声明类型:
ruby
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

Inertia Prop Options in Alba

Alba中的Inertia Prop选项

The
inertia:
option on attributes/associations maps to
InertiaRails
prop types:
ruby
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
MANDATORY — READ ENTIRE FILE when using grouped defer, merge with
match_on
, scroll props, or combining multiple options:
references/prop-options.md
(~60 lines) — full syntax for all
inertia:
option variants and
inertia_prop
alternative syntax.
Do NOT load for basic
inertia: :defer
,
inertia: :optional
, or
inertia: :once
— the shorthand above is sufficient.
属性/关联上的
inertia:
选项对应
InertiaRails
的prop类型:
ruby
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
强制要求——当使用分组延迟、带
match_on
的合并、滚动props或组合多个选项时,请通读整个文档:
references/prop-options.md
(约60行)——包含所有
inertia:
选项变体的完整语法,以及
inertia_prop
替代语法。
若仅使用基础的
inertia: :defer
inertia: :optional
inertia: :once
,则无需查看该文档
——上述简写语法已足够。

Troubleshooting

故障排查

SymptomCauseFix
TypeScript type is all
unknown
Missing
typelize_from
Add
typelize_from ModelName
when resource name doesn't match model
inertia:
option has no effect
Missing helperEnsure
helper Alba::Inertia::Resource
is in
ApplicationResource
Types not regeneratingServer not runningTypelizer watches files in dev only. Run
bin/rake typelizer:generate
manually
NoMethodError
for
typelize
Missing helperEnsure
helper Typelizer::DSL
is in
ApplicationResource
Convention-based rendering picks wrong resourceNaming mismatchResource must be
{Controller}{Action}Resource
(e.g.,
UsersIndexResource
for
UsersController#index
)
to_inertia
undefined
Missing includeController needs
include Alba::Inertia::Controller
症状原因解决方法
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

Related Skills

相关技能

  • Prop types
    inertia-rails-controllers
    (defer, once, merge, scroll)
  • TypeScript config
    inertia-rails-typescript
    (InertiaConfig in globals.d.ts)
  • Prop类型
    inertia-rails-controllers
    (defer、once、merge、scroll)
  • TypeScript配置
    inertia-rails-typescript
    (globals.d.ts中的InertiaConfig)