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

Rails项目报错:ArgumentError in Products#show,nil非ActiveModel兼容对象

问题描述

我正在开发一个杂货电商网站,希望在Product详情页展示OutletProduct的详情,已创建名为_outletproductform.html.erb的局部视图并放置在Product的show页面,但出现报错。

报错信息:ArgumentError in Products#show , 'nil' is not an ActiveModel-compatible object. It must implement :to_partial_path


相关代码

Product控制器

class ProductsController < ApplicationController

 def category
  @category = Category.find(params[:id])
 end

 def index
  @products = Product.all
 end

 def show
  @product = Product.find(params[:id])
  @outlet_product = OutletProduct.find(params[:id])
 end

 def new
  @product = Product.new
  @category = Category.all
 end

 def create
  @product = Product.new(product_params)
  @category_id = Category.all
  if @product.save
   flash[:success] = "Succesful create!"
   redirect_to @product
 else
   render 'new'
 end
end

 private

def product_params
  params.require(:product).permit(:name, :quantity, :price,
                                  :category_id, :cost)
end
end

show.html.erb

<% provide(:title, @product.name)%>

<%= render @product %>
<%= render @outletproductform %>
<div class="row">
 <aside class="col-md-4">
  <section class="stats">
   <%= render 'shared/stats' %>
  </section>
 <div>
   <%= link_to "Add to Outlet", new_outlet_product_path %>
   <%= link_to "Edit", edit_product_path %>
   <%= link_to "Back to products", products_path %>
 </div>
 </aside>
</div>

_outletproductform.html.erb

<div>
 <table class="styled-table">
  <thead>
    <tr>
     <th>Outlet</th>
     <th>Quantity</th>
     <th>Selling Price</th>
     <th>Last Cost</th>

    </tr>
 </thead>
 <tbody>
   <tr>
    <td><%= outlet_product.outlet.name %></td>
    <td><%= outlet_product.quantity %></td>
    <td><%= outlet_product.selling_price %></td>
    <td><%= outlet_product.last_cost %></td>
  </tr>

 </tbody>
</div>

OutletProduct数据库Schema

create_table "outlet_products", force: :cascade do |t|
t.integer "outlet_id"
t.integer "product_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.decimal "selling_price"
t.decimal "last_cost"
t.decimal "quantity"
end

问题分析与解决

1. 局部视图渲染方式错误

show.html.erb中<%= render @outletproductform %>是错误写法——@outletproductform变量从未定义,导致它为nil,这就是报错的直接原因。

正确渲染局部视图需要指定视图名称,并传递所需变量:

<%# 替换原渲染代码 %>
<%= render 'outletproductform', outlet_product: @outlet_product %>

2. OutletProduct查询逻辑错误

控制器show方法中用OutletProduct.find(params[:id])查询是错误的——params[:id]是当前Product的ID,而非OutletProduct的ID。根据Schema,OutletProduct与Product通过product_id关联,需查询当前产品对应的OutletProduct:

首先在模型中建立关联:

  • Product模型添加:
has_many :outlet_products
  • OutletProduct模型添加:
belongs_to :product
belongs_to :outlet

然后修改控制器show方法:

def show
  @product = Product.find(params[:id])
  # 获取当前产品下所有OutletProduct(若为一对一则用.first)
  @outlet_products = @product.outlet_products
end

3. 局部视图适配多数据场景

如果要展示当前产品的所有OutletProduct,需在局部视图中遍历数据,并补上遗漏的</table>闭合标签:

<div>
 <table class="styled-table">
  <thead>
    <tr>
     <th>Outlet</th>
     <th>Quantity</th>
     <th>Selling Price</th>
     <th>Last Cost</th>
    </tr>
 </thead>
 <tbody>
   <% outlet_products.each do |outlet_product| %>
   <tr>
    <td><%= outlet_product.outlet.name %></td>
    <td><%= outlet_product.quantity %></td>
    <td><%= outlet_product.selling_price %></td>
    <td><%= outlet_product.last_cost %></td>
   </tr>
   <% end %>
 </tbody>
 </table>
</div>

对应渲染代码也要改为传递集合:

<%= render 'outletproductform', outlet_products: @outlet_products %>

其他小问题修复

  • show.html.erb中edit_product_path需传递参数:edit_product_path(@product)
  • 控制器create方法中@category_id = Category.all是冗余代码,可删除

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:50:29