如何在rails控制器中处理ActiveRecord :: RecordNotFound?

guy*_*ler 14 activerecord ruby-on-rails

我有一个用户和活动的应用程序.每个用户都有几个事件.当用户想要查看特定事件时,他将执行此操作:

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
Run Code Online (Sandbox Code Playgroud)

如果没有为用户找到事件,则意味着他使用URL播放并且他试图获得的事件不属于他.我想要将他重定向到主页面,或者只显示一个错误,表明找不到该事件.如果我尝试运行上面的代码,则会触发此错误:

AbstractController::DoubleRenderError in EventsController#show 
Run Code Online (Sandbox Code Playgroud)

解决这个问题的最佳方法是什么?

小智 20

返回重定向后

begin
 @userEvents = current_user.event
 @event = @userEvents.find(params[:id])
rescue ActiveRecord::RecordNotFound  
 redirect_to :controller => "main", :action => "index"
 return
end
Run Code Online (Sandbox Code Playgroud)


noo*_*odl 14

调用redirect_to不会从您的操作方法返回,这就是为什么移动到respond_to块导致DoubleRenderError.解决这个问题的一种方法是:

redirect_to :controller => "main", :action => "index" and return
Run Code Online (Sandbox Code Playgroud)

但是,更好的解决方案可能是以声明方式从此异常中解救,或者只是让它传播到客户端.前者看起来像这样:

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
Run Code Online (Sandbox Code Playgroud)

如果您只是让异常恶化,用户将public/404.html在生产模式下看到该页面.


Vij*_*han 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
Run Code Online (Sandbox Code Playgroud)

创建一个页面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 %>
Run Code Online (Sandbox Code Playgroud)

在en.yml

en:
  errors:
    "404":
      description: "The page you are looking for does not exist!"
      heading: "Record not found"
      subheading: ""
Run Code Online (Sandbox Code Playgroud)