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
相关产品推荐
相关产品推荐

