只是想知道处理以下问题的最佳方法,因为互联网上似乎存在相互矛盾的信息。我的代码开始像这样生活..
@merchant = Merchant.find_by_name(params[:merchant])
@products = @merchant.products.all.paginate(:page => params[:page])
现在效果很好,直到您点击商家不存在的网址,即/merchants/thisonedontexist/
,此时我收到以下错误:
`undefined method `products' for nil:NilClass`
我理解为什么会收到此错误。
然后经过一些研究后,我决定用BANG(!)将我的代码更改为以下代码,这会引发NoRecordFound错误,因此它永远不会到达下一行,麻烦的是,我现在得到一个丑陋的错误:
@merchant = Merchant.find_by_name!(params[:merchant])
@products = @merchant.products.all.paginate(:page => params[:page])
错误是:ActiveRecord::RecordNotFound
经过一番研究后,我做了以下工作,并将这些请求重定向到404 ......
def show
@merchant = Merchant.find_by_name(params[:merchant])
if !@merchant.nil?
@products = @merchant.products.all.paginate(:page => params[:page])
else
redirect_to :status => 404
end
end
这似乎有效,但看起来非常笨重......这里的最佳做法是什么?
我希望它只显示一个类似"Sorry no category exists"
的页面。
P.S。我是Rails的新手,也许这个问题有一个非常明显的答案
答案 0 :(得分:2)
使用爆炸版是最好的方法。 NoMethodError让我觉得你没有正确处理应用程序工作流程。
此外,使用bang版本可以简化代码。
在生产中,ActiveRecord::RecordNotFound
被拯救为404.这意味着,当错误被提出时,Rails将挽救错误并默认显示404错误页面,其中包含404状态代码。
请参阅source code。
您可以简化代码
def show
@merchant = Merchant.find_by_name!(params[:merchant])
@products = @merchant.products.all.paginate(:page => params[:page])
end
答案 1 :(得分:0)
正如@simone所说,您可以将代码简化为
def show
@merchant = Merchant.find_by_name!(params[:merchant])
@products = @merchant.products.all.paginate(:page => params[:page])
end
现在,当找不到@merchant时,会引发异常。幸运的是,rails提供了一个很好的解决方案来很好地处理异常。
在您的控制器内(或ApplicationController
,如果您想使其通用),您可以写
rescue_from ActiveRecord::RecordNotFound, :with => :handle_not_found
def handle_not_found
# either
flash[:error] = ... some appropriate error message ...
redirect_to :root # or some relevant path
end
因此,在该方法中,您可以根据需要执行任何想要处理异常的操作。
答案 2 :(得分:-1)
控制器
def show
@merchant = Merchant.find_by_name(params[:merchant])
@products = @merchant.products.all.paginate(:page => params[:page]) if @merchant
end
在您的视图/show.html.erb 中
if @merchant
...
...your code here
else
<div>No such merchant</div>
end