mcpField
A
active-interaction-coder

active-interaction-coder

github.com/majesticlabs-dev开发5062 次安装7 周前更新
代码仓库

关于 active-interaction-coder

将 Rails 业务操作组织为带类型的 ActiveInteraction 类的编码技能,介绍输入声明、验证、组合、使用 `.run` 或 `.run!` 执行以及测试。

主要功能

  1. 01带类型的操作输入
  2. 02标准 Rails 验证
  3. 03可组合的交互操作
  4. 04使用 `.run` 和 `.run!` 执行
  5. 05交互操作测试模式

适用场景

  1. 01实现用户注册操作
  2. 02组合多个业务操作
  3. 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