用途
Form Object Patterns 是一个面向 Rails 8 的 AI 技能,用于创建表单对象(Form Object),以封装复杂表单逻辑,并按照 TDD 工作流进行开发。它适合在以下情况使用:多模型表单(如 user + profile + address)、搜索/筛选表单(非持久化)、向导/多步表单、带校验的虚拟属性,以及需要与 ActiveRecord 模型解耦的场景。
何时使用表单对象(原技能给出的对照):
- 单模型 CRUD:不需要,直接用模型
- 多模型创建:需要
- 跨模型复杂校验:需要
- 搜索/筛选表单:需要
- 向导/多步表单:需要
- API 参数转换:需要
- 联系表单(无持久化):需要
TDD 工作流
技能给出的步骤清单为:
- Step 1:定义表单需求
- Step 2:编写表单对象 spec(RED)
- Step 3:运行 spec(失败)
- Step 4:创建表单对象
- Step 5:运行 spec(GREEN)
- Step 6:接入控制器
- Step 7:创建视图表单
项目结构
技能建议的目录结构如下:
app/
├── forms/
│ ├── application_form.rb # Base class
│ ├── registration_form.rb # Multi-model
│ ├── search_form.rb # Non-persisted
│ └── wizard/
│ ├── base_form.rb
│ ├── step_one_form.rb
│ └── step_two_form.rb
spec/forms/
├── registration_form_spec.rb
└── search_form_spec.rb
基础表单类
技能提供的基础类代码如下(未作改动):
# app/forms/application_form.rb
class ApplicationForm
include ActiveModel::Model
include ActiveModel::Attributes
include ActiveModel::Validations
def self.model_name
ActiveModel::Name.new(self, nil, name.chomp("Form"))
end
def persisted?
false
end
def save
return false unless valid?
persist!
true
rescue ActiveRecord::RecordInvalid => e
errors.add(:base, e.message)
false
end
private
def persist!
raise NotImplementedError
end
end
四种模式
技能说明共实现四种模式,并配有完整 TDD 周期,详见 patterns.md:
Pattern 1:多模型注册表单
在一个事务中创建 User 与 Account;校验邮箱唯一性和密码确认;保存后暴露 form.user 与 form.account。包含 spec(RED)与实现(GREEN)。
Pattern 2:搜索/筛选表单
非持久化表单,带有 query、type、status 与日期范围等筛选条件,作为可链式作用域应用;为视图暴露 results 与 any_filters? 辅助方法。包含 spec 与实现。
Pattern 3:向导/多步表单
Wizard::BaseForm 提供 next_step、previous_step、first_step?、last_step? 与 progress_percentage;每个步骤子类声明自己的属性与校验。
Pattern 4:联系表单(无持久化)
直接覆写 #save(不使用 persist!);通过 deliver_later 派发,不写入数据库。
控制器与视图集成
技能说明详见 controller-and-views.md,内容包括:
- 带 allow_unauthenticated_access 的标准控制器,包含 #new / #create,失败时 render :new, status: :unprocessable_entity
- 使用 form_with model: @form 的视图及错误显示
- 搜索表单局部模板,包含下拉框、日期字段,以及筛选激活时的“Clear”链接
关键约定:
- 使用 form_with model: @form, url: explicit_path —— 表单对象不是 ActiveRecord 模型
- 使用 params.require(:model_name).permit(...) 允许参数,model_name 为去掉“Form”后的蛇形命名类名
- 失败时始终 render :new, status: :unprocessable_entity,以便 Turbo 处理响应
检查清单
技能提供的检查清单如下:
- Spec 先写(RED)
- 继承 ApplicationForm 或包含 ActiveModel::Model
- 使用类型声明属性
- 定义校验
- #save 方法带事务(如为多模型)
- 控制器使用表单对象
- 视图使用 form_with model: @form
- 错误处理到位
- 所有 specs 为 GREEN
参考资料
- patterns.md —— 全部四种模式的完整 TDD 实现:多模型注册、搜索/筛选、向导/多步、联系表单
- controller-and-views.md —— 带未认证访问的控制器、注册表单视图与搜索表单局部模板
限制
本技能资料未提供关于收费、价格、平台支持范围或实际效果的信息;如需了解这些内容,请以官方渠道为准。