You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails关联子模型渲染报错:undefined method `humanize' for nil

问题解决与嵌套模型配置修正

核心错误原因

你在ActivitiesController#show中写了@refusals = @activity.refusals.build,这行代码会创建一个未保存的空Refusal对象并添加到@activity.refusals集合里。当视图执行<%= render @activity.refusals %>时,会渲染集合内所有对象——包括这个空对象,而空对象的reason字段为nil,调用humanize自然会抛出undefined method 'humanize' for nil错误。

分步修正方案

1. 修正Activity控制器的show方法

将创建空对象的代码改为单数形式,仅用于新建表单,避免污染已有的关联集合:

class ActivitiesController < ApplicationController
  before_action :set_activity, only: %i[ show edit update destroy ]

  def show
    # 用单数@refusal,仅给新建表单使用,不修改@activity.refusals集合
    @refusal = @activity.refusals.build
  end
  # 其余方法省略
end

2. 修正Refusals控制器的create方法

  • 移除末尾错误的redirect_to article_path(@article)(@article未定义,且会覆盖前面的响应跳转)
  • 保存成功后跳转到关联的Activity详情页,符合嵌套模型的使用逻辑:
class RefusalsController < ApplicationController
  def create
    @activity = Activity.find(params[:activity_id])
    @refusal = @activity.refusals.new(refusal_params)

    respond_to do |format|
      if @refusal.save
        # 跳转到所属的Activity详情页,而非Refusal单独页面
        format.html { redirect_to activity_url(@activity), notice: "Refusal was successfully created." }
        format.json { render :show, status: :created, location: @refusal }
      else
        # 保存失败时回到Activity详情页,重新渲染表单
        format.html { render "activities/show", status: :unprocessable_entity }
        format.json { render json: @refusal.errors, status: :unprocessable_entity }
      end
    end
    # 删除这行错误的redirect代码
    # redirect_to article_path(@article)
  end
  # 其余方法省略
end

3. 修正Activity详情视图的表单渲染

确保表单使用的变量名与控制器定义一致(单数@refusal):

<div class="mx-auto md:w-2/3 w-full flex">
  <div class="mx-auto">
    <%= render @activity %>
    <p class="my-5">
      <strong class="block font-medium mb-1">Refusals:</strong>
    </p>
    <%= render @activity.refusals %>
    <p class="my-5">add refusal</p>
    <!-- 变量名改为@refusal,与控制器定义对应 -->
    <%= render 'refusals/form', refusal: @refusal %>
    <!-- 其余内容省略 -->
  </div>
</div>

4. (可选)给局部视图加nil保护

为避免类似问题,给局部视图中可能为nil的字段添加安全调用:

<div id="<%= dom_id refusal %>">
  <p class="my-5">
    <strong class="block font-medium mb-1">Activity:</strong>
    <%= refusal.activity_id %>
  </p>

  <p class="my-5">
    <strong class="block font-medium mb-1">Reason:</strong>
    <%= refusal.reason&.humanize || 'N/A' %>
  </p>

  <p class="my-5">
    <strong class="block font-medium mb-1">Description:</strong>
    <%= refusal.description || 'N/A' %>
  </p>

  <p class="my-5">
    <strong class="block font-medium mb-1">Refuser:</strong>
    <%= refusal.refuser || 'N/A' %>
  </p>

</div>

Rails 7嵌套模型脚手架生成参考

如果从头用脚手架生成嵌套模型,可按以下步骤执行:

  1. 生成父模型Activity:
rails g scaffold Activity section:references status:integer activity_type:integer
rails db:migrate
  1. 生成嵌套的Refusal模型并关联Activity:
rails g scaffold Refusal activity:references reason:integer description:string refuser:string
rails db:migrate
  1. 在config/routes.rb中配置嵌套路由:
resources :activities do
  resources :refusals, only: [:create, :destroy] # 根据需求调整允许的动作
end
  1. 按前面的修正逻辑调整控制器和视图,确保新建表单在Activity详情页,操作后返回父页面。

内容的提问来源于stack exchange,提问作者baed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 19:12:45