我有一个包含用户和活动的应用。每个用户都有几个事件。当用户想要查看特定事件时,他将采取此操作:
def show
begin
@userEvents = current_user.event
@event = @userEvents.find(params[:id])
rescue ActiveRecord::RecordNotFound
redirect_to :controller => "main", :action => "index"
end
respond_to do |format|
format.html # show.html.erb
format.json { render json: @event }
end
end
如果没有找到该用户的事件,则表示他使用了URL并且他试图获得的事件不属于他。我想要将他重定向到主页面,或者只显示一个错误,表明找不到该事件。如果我尝试运行上面的代码,则会触发此错误:
AbstractController::DoubleRenderError in EventsController#show
解决此问题的最佳方法是什么?
答案 0 :(得分:20)
重定向后返回
begin
@userEvents = current_user.event
@event = @userEvents.find(params[:id])
rescue ActiveRecord::RecordNotFound
redirect_to :controller => "main", :action => "index"
return
end
答案 1 :(得分:14)
调用redirect_to
不会从您的操作方法返回,这就是为什么转到respond_to
块会导致DoubleRenderError
。解决这个问题的一种方法是:
redirect_to :controller => "main", :action => "index" and return
但是,更好的解决方案可能是以声明方式rescue from此异常,或者只是让它传播到客户端。前者看起来像这样:
class YourController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, with: :dude_wheres_my_record
def show
# your original code without the begin and rescue
end
def dude_where_my_record
# special handling here
end
end
如果只是让异常更快,用户将在生产模式下看到public/404.html
页面。
答案 2 :(得分:5)
在应用程序控制器中,请写:
rescue_from (ActiveRecord::RecordNotFound) { |exception| handle_exception(exception, 404) }
protected
def handle_exception(ex, status)
render_error(ex, status)
logger.error ex
end
def render_error(ex, status)
@status_code = status
respond_to do |format|
format.html { render :template => "error", :status => status }
format.all { render :nothing => true, :status => status }
end
end
创建页面error.html.erb
<div class="page-header">
<h1>
<%= t "errors.#{@status_code}.heading" %>
<small><%= t "errors.#{@status_code}.subheading" %></small>
</h1>
</div>
<p><%= t "errors.#{@status_code}.description" %></p>
<% if defined? root_path %>
<%= link_to t(:return_to_home), root_path %>
<% end %>
和en.yml
en:
errors:
"404":
description: "The page you are looking for does not exist!"
heading: "Record not found"
subheading: ""