Rails股票应用Stocks#show页报StockQuote无destroy方法错误
Rails股票应用删除按钮崩溃问题排查
问题现象
- 股票市场Web应用的
stocks/show.html.erb页面点击删除按钮时触发运行崩溃 - Rails抛出明确错误:
undefined method 'destroy' for #<StockQuote::Stock:0x...>,即第三方API返回的行情数据对象不存在destroy方法
问题根因
核心错误是局部视图变量污染,覆盖了控制器传入的数据库模型实例:
- 控制器
set_stock前置方法原本正确查询出了数据库中Stock表的ActiveRecord记录,赋值给@stock,这个对象自带destroy等数据库操作方法 - 页面执行
<%= render @stock %>渲染Stock局部视图时,局部视图首行写了<% @stock= StockQuote::Stock.quote(stock.ticker) %>,直接把外层作用域的@stock变量替换成了stock_quotegem返回的行情数据对象,这类第三方API封装的对象没有数据库删除相关的方法 - 局部视图渲染完成返回show主页面后,后续编辑、删除按钮读取到的
@stock已经是API返回的行情对象,不再是数据库里的Stock记录,路由生成、方法调用全部出错
额外错误点:报错提取的代码显示删除按钮被误写为<%= button_to "Delete this stock", @stock.destroy, method: :delete %>,视图层绝对不能直接调用.destroy方法——该方法是控制器处理删除请求时执行的逻辑,写在视图中会在页面渲染阶段就直接触发删除,完全跳过用户点击交互。
修复方案
1. 修改Stock局部视图,避免变量覆盖
将局部视图中存储API行情数据的实例变量重命名,不要和控制器传入的@stock重名,防止作用域污染:
<%# 原代码用@stock存API数据会覆盖外层变量,改用独立变量名@stock_quote %> <% @stock_quote = StockQuote::Stock.quote(stock.ticker) %> <div id="<%= dom_id stock %>"> <p> <strong>Ticker:</strong> <%= @stock_quote.symbol %> </p> <p> <strong>Open</strong> $<%= @stock_quote.open %> </p> <p> <strong>Price</strong> $<%= @stock_quote.latest_price %> </p> <p> <strong>Close</strong> $<%= @stock_quote.close %> </p> <p> <strong>Company Name</strong> <%= @stock_quote.company_name %> </p> <p> <strong>Primary Exchange</strong> <%= @stock_quote.primary_exchange %> </p> <p> <strong>Volume</strong> <%= number_with_delimiter(@stock_quote.volume, delimiter: ',') %> </p> <p> <strong>Market Cap</strong> $<%= number_with_delimiter(@stock_quote.market_cap, delimiter: ',') %> </p> </div>
2. 修正show.html.erb的删除按钮代码
删除按钮中移除错误的.destroy调用,保持Rails路由生成的标准写法:
<%= render @stock %> <div> <%= link_to "Edit this stock", edit_stock_path(@stock) %> | <%= link_to "Back to stocks", stocks_path %> <%= button_to "Delete this stock", @stock, method: :delete %> </div>
3. 可选优化
当前Stocks控制器的show动作中存在冗余代码@stocks = Stock.all,该变量在show视图中未被使用,可以删除以减少不必要的数据库查询。
内容的提问来源于stack exchange,提问作者Maikkeru
相关产品推荐
相关产品推荐

