rails-hotwire-expert

star 0

当用 Rails 7+ 搭建带 Hotwire 的 Web 应用、做实时局部更新或后台任务时使用;产出 Active Record 防 N+1 查询、Turbo Frames/Streams 局部刷新、Action Cable 通道、Sidekiq Worker 与 RSpec 测试套件;不适用于非 Rails 栈、纯前端 SPA、仅需基础 Ruby 语法、或无法改动 Gemfile 与迁移的场景;触发词:Rails、Hotwire、Turbo、Action Cable、Sidekiq、Active Record、RSpec

findscripter By findscripter schedule Updated 6/2/2026

name: rails-hotwire-expert title: Rails 7+ 与 Hotwire 开发专家 description: 当用 Rails 7+ 搭建带 Hotwire 的 Web 应用、做实时局部更新或后台任务时使用;产出 Active Record 防 N+1 查询、Turbo Frames/Streams 局部刷新、Action Cable 通道、Sidekiq Worker 与 RSpec 测试套件;不适用于非 Rails 栈、纯前端 SPA、仅需基础 Ruby 语法、或无法改动 Gemfile 与迁移的场景;触发词:Rails、Hotwire、Turbo、Action Cable、Sidekiq、Active Record、RSpec domain: 研发/backend triggers: [Rails 7, Ruby on Rails, Hotwire, Turbo Frames, Turbo Streams, Stimulus, Action Cable, WebSocket, Active Record 优化, N+1 查询, includes/eager_load, Sidekiq 后台任务, RSpec Rails, strong parameters, service object] tags: [rails, hotwire, turbo, active-record, sidekiq, action-cable, rspec, 研发] level: 精通 status: stable agents: [claude-code, codex, cursor, gemini-cli] tools: [ruby, rails, hotwire, turbo-rails, stimulus, action-cable, sidekiq, rspec-rails, rubocop, factory_bot] requires: [] related: [ruby-pro, laravel-app-specialist, django-async-pro, sveltekit-fullstack] combines_with: [websocket-realtime-engineer, rest-api-endpoint-builder] license: MIT source: jeffallan/claude-skills source_license: MIT

何时使用

适用:

  • 用 Rails 7+ 搭建或扩展 Web 应用,前端走 Hotwire(Turbo + Stimulus)而非独立 SPA。
  • 需要局部页面刷新(Turbo Frames / Streams)、WebSocket 实时推送(Action Cable)。
  • 把慢操作(发信、导出、第三方调用)下沉到 Sidekiq 后台任务。
  • 优化 Active Record:消除 N+1、补索引、加缓存;用 RSpec 补齐模型/请求/系统测试。

不该用(负边界):

  • 非 Rails 栈,或后端用其他语言运行时。
  • 纯前端 SPA(React/Vue 独立前端 + Rails 仅作 JSON API 也尽量用 Hotwire 思路,否则另选技能)。
  • 只需基础 Ruby 语法解释。
  • 无法改动 Gemfile、迁移文件或工具链(代码与迁移无从落地)。

步骤

  1. 梳理需求:识别模型与关联、路由、实时需求、后台任务边界。
  2. 脚手架:rails generate model User name:string email:stringrails generate controller Users
  3. 跑迁移:rails db:migrate,用 rails db:schema:dump 校验 schema。
    • 迁移失败:查 db/schema.rb 冲突 → rails db:rollback → 修正重试。
  4. 实现:写瘦控制器(强参数)+ 模型(关联/校验),复杂逻辑放 service object;按需接入 Hotwire / Action Cable / Sidekiq。
  5. 验证:bundle exec rspec 必须全绿;bundle exec rubocop 过风格检查。
    • 测试失败:加 --format documentation 看细节,修正失败用例后重跑。
    • 评审中冒出 N+1:补 includes/eager_load 后重跑。
  6. 优化:审计 N+1、为 WHERE/ORDER BY/JOIN 列补索引、加缓存。

指令

  • 实现一个 Rails 特性时,按需产出:迁移文件 → 模型(含关联与校验)→ 控制器(RESTful + 强参数)→ 视图或 Hotwire 装配 → RSpec(模型 + 请求)→ 关键架构决策一句话说明。
  • 集合查询凡涉及关联,一律用 includes/eager_load 防 N+1。
  • 控制器保持瘦身,复杂业务逻辑抽到 service object。
  • 慢操作走 perform_later 入 Sidekiq,绝不在请求周期内同步执行。
  • 原始 SQL 必须参数化或 sanitize_sql;勿在 URL 直接暴露内部自增 ID(按需用 UUID/slug)。

示例

防 N+1(includes / eager_load):

# BAD — 触发 N+1
posts = Post.all
posts.each { |post| puts post.author.name }

# GOOD — 预加载关联
posts = Post.includes(:author).all

# GOOD — eager_load 强制 JOIN(按关联字段过滤时用)
posts = Post.eager_load(:author).where(authors: { verified: true })

Turbo Frame 局部更新:

<%# app/views/posts/index.html.erb %>
<%= turbo_frame_tag "posts" do %>
  <%= render @posts %>
  <%= link_to "Load More", posts_path(page: @next_page) %>
<% end %>

<%# app/views/posts/_post.html.erb %>
<%= turbo_frame_tag dom_id(post) do %>
  <h2><%= post.title %></h2>
  <%= link_to "Edit", edit_post_path(post) %>
<% end %>
# app/controllers/posts_controller.rb
def index
  @posts = Post.includes(:author).page(params[:page])
  @next_page = @posts.next_page
end

Sidekiq Worker 模板:

# app/jobs/send_welcome_email_job.rb
class SendWelcomeEmailJob < ApplicationJob
  queue_as :default
  sidekiq_options retry: 3, dead: false

  def perform(user_id)
    user = User.find(user_id)
    UserMailer.welcome(user).deliver_now
  rescue ActiveRecord::RecordNotFound => e
    Rails.logger.warn("SendWelcomeEmailJob: user #{user_id} not found — #{e.message}")
    # 记录已不存在,不再 raise,重试无意义
  end
end

# 从控制器或模型回调入队
SendWelcomeEmailJob.perform_later(user.id)

强参数 + 瘦控制器:

# app/controllers/posts_controller.rb
class PostsController < ApplicationController
  before_action :set_post, only: %i[show edit update destroy]

  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to @post, notice: "Post created."
    else
      render :new, status: :unprocessable_entity
    end
  end

  private

  def set_post
    @post = Post.find(params[:id])
  end

  def post_params
    params.require(:post).permit(:title, :body, :published_at)
  end
end

注意事项

  • 必做:每个关联集合查询防 N+1;测试争取 >95% 覆盖;复杂逻辑用 service object;为 WHERE/ORDER BY/JOIN 列补索引;慢操作下沉 Sidekiq。
  • 禁做:跳过迁移直接改 schema;用未 sanitize 的原始 SQL;无脑在 URL 暴露内部 ID。
  • 表单校验失败时 render :new, status: :unprocessable_entity(422),Turbo 才会正确替换帧而非误判成功跳转。
  • Sidekiq 任务参数只传 ID 等可序列化值,不要传整个 AR 对象。

互见

  • requires:ruby-pro —— Rails 之上需先具备 Ruby/Rails 惯用法与 RSpec 基础
  • related:backend-architecture-patternsdatabase-design-advisorcode-reviewer
  • combines_with:rest-api-endpoint-builder —— Rails API 模式下做端点契约;database-design-advisor —— 配合做迁移与索引设计

采编自 jeffallan/claude-skills(MIT)。

Install via CLI
npx skills add https://github.com/findscripter/everything-skills --skill rails-hotwire-expert
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator
findscripter
findscripter Explore all skills →