关于 active-interaction-coder
将 Rails 业务操作组织为带类型的 ActiveInteraction 类的编码技能,介绍输入声明、验证、组合、使用 `.run` 或 `.run!` 执行以及测试。
主要功能
- 01带类型的操作输入
- 02标准 Rails 验证
- 03可组合的交互操作
- 04使用 `.run` 和 `.run!` 执行
- 05交互操作测试模式
适用场景
- 01实现用户注册操作
- 02组合多个业务操作
- 03使用有效输入测试操作
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ majesticlabs-dev/ majestic-marketplace --skill active-interaction-coder安装后在 Claude Code 中输入/active-interaction-coder确认已加载。
详细介绍
ActiveInteraction Coder
作为服务对象的结构化替代方案,实现类型化业务操作。
为什么选择 ActiveInteraction,而不是服务对象
| 服务对象 | ActiveInteraction |
|---|---|
| 没有标准接口 | 统一的 .run / .run! |
| 手动进行类型检查 | 内置类型声明 |
| 手动进行验证 | 标准 Rails 验证 |
| 难以组合 | 原生组合 |
| 样板代码冗长 | 简洁且自描述 |
设置
# Gemfile
gem "active_interaction", "~> 5.3"
简单交互
# app/interactions/users/create.rb
module Users
class Create < ActiveInteraction::Base
# Typed inputs
string :email
string :name
string :password, default: nil
# Validations
validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
validates :name, presence: true
# Main logic
def execute
user = User.create!(
email: email,
name: name,
password: password || SecureRandom.alphanumeric(32)
)
UserMailer.welcome(user).deliver_later
user # Return value becomes outcome.result
end
end
end
运行交互
# In controller
def create
outcome = Users::Create.run(
email: params[:email],
name: params[:name]
)
if outcome.valid?
redirect_to outcome.result, notice: "User created"
else
@errors = outcome.errors
render :new, status: :unprocessable_entity
end
end
# With bang method (raises on error)
user = Users::Create.run!(email: "[email protected]", name: "John")
输入类型
class MyInteraction < ActiveInteraction::Base
# Primitives
string :name
integer :age
float :price
boolean :active
symbol :status
# Date/Time
date :birthday
time :created_at
date_time :scheduled_at
# Complex types
array :tags
hash :metadata
# Model instances
object :user, class: User
# Typed arrays
array :emails, default: [] do
string
end
# Optional with default
string :optional_field, default: nil
integer :count, default: 0
end
组合交互
module Users
class Register < ActiveInteraction::Base
string :email, :name, :password
def execute
# Compose calls another interaction
user = compose(Users::Create,
email: email,
name: name,
password: password
)
# Errors automatically merged if nested fails
compose(Users::SendWelcomeEmail, user: user)
user
end
end
end
控制器模式
class ArticlesController < ApplicationController
def create
outcome = Articles::Create.run(
title: params[:article][:title],
body: params[:article][:body],
author: current_user
)
if outcome.valid?
redirect_to article_path(outcome.result), notice: "Article created"
else
@article = Article.new(article_params)
@article.errors.merge!(outcome.errors)
render :new, status: :unprocessable_entity
end
end
end
测试交互
RSpec.describe Users::Create do
let(:valid_params) { { email: "[email protected]", name: "John" } }
it "creates user with valid inputs" do
expect { described_class.run(valid_params) }
.to change(User, :count).by(1)
end
it "returns valid outcome" do
outcome = described_class.run(valid_params)
expect(outcome).to be_valid
expect(outcome.result).to be_a(User)
end
it "validates email format" do
outcome = described_class.run(valid_params.merge(email: "invalid"))
expect(outcome).not_to be_valid
expect(outcome.errors[:email]).to be_present
end
end
高级模式
有关组合、错误处理和自定义类型,请参阅:
references/active-interaction.md
评论
支持 Markdown