全书目录

第二十八篇:Ruby on Rails 完全指南 —— 城市脚手架工务署宇宙

第七章:Controller —— 受理窗口,不是把所有活都堆进去的大厅主任

1 分钟 372 字 第 500 / 962 个阅读单元

控制器是受理窗口。

它接请求、拿参数、调业务、决定返回什么。
但它不该变成“一切都写在这里”。

先看一个干净的例子:

ruby
class PermitsController < ApplicationController
  before_action :set_permit, only: %i[show edit update destroy]

  def index
    @permits = Permit.order(created_at: :desc)
  end

  def show
  end

  def new
    @permit = Permit.new
  end

  def create
    @permit = Permit.new(permit_params)

    if @permit.save
      redirect_to @permit, notice: "施工许可单已创建。"
    else
      render :new, status: :unprocessable_entity
    end
  end

  def edit
  end

  def update
    if @permit.update(permit_params)
      redirect_to @permit, notice: "施工许可单已更新。"
    else
      render :edit, status: :unprocessable_entity
    end
  end

  def destroy
    @permit.destroy
    redirect_to permits_path, notice: "施工许可单已删除。"
  end

  private

  def set_permit
    @permit = Permit.find(params[:id])
  end

  def permit_params
    params.expect(permit: [:title, :district, :status, :starts_on])
  end
end

这里有几件事要看懂:

  • before_action 是窗口前置检查
  • redirect_to 是“办完后让你去另一个大厅”
  • render :new, status: :unprocessable_entity 是“资料有误,原窗口退回并保留错误信息”
  • permit_params 是强参数白名单

关于强参数,要特别提一句:

截至 2026 年的新官方指南里,你会看到 params.expect(...)
但在大量老项目里,你仍然会经常看到:

ruby
params.require(:permit).permit(:title, :district, :status, :starts_on)

两种都能遇到。
读老代码别慌,都是工务署在做“只允许这些字段入场”。

控制器最常见的大坑是:

text
参数校验写这里
SQL 写这里
第三方请求写这里
邮件写这里
权限写这里
报表写这里
事务写这里
返回拼装也写这里

然后一个 action 200 行起步。

那不是受理窗口。
那是把整个工务署塞进一个柜台。