在特定路线上使用rescue_from的Rails

时间:2016-05-14 20:24:53

标签: ruby-on-rails ruby-on-rails-4 model-view-controller

我有一个用户控制器,如果我愿意,我可以解决错误,如果没有找到用户,并将它们重定向到适当的页面。但我只想在某些路由而不是所有路由上使用rescue_from方法。所以,几乎与

相似

rescue_from ActiveRecord::RecordNotFound, with: :record_not_found, except: [:new, :edit]

有办法做到这一点吗?感谢帮助!

class UserController < ApplicationController

  before_action :get_user

  rescue_from ActiveRecord::RecordNotFound, with: :record_not_found

  def show
  end

  def new
  end

  def create
  end

  def edit
  end

  def update
  end

  private
    def get_user
      User.find(params[:id])
    end

    def record_not_found
      redirect_to user_path, error: "Sorry, no user found."
    end 
end

4 个答案:

答案 0 :(得分:1)

让我们首先只在需要时调用回调:

before_action :get_user, only: [:show, :edit, :update, :destroy]

但是,查询的记录甚至没有分配给变量,因此可以在以后使用。让我们解决一下:

class UserController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  # ...

  private 

    def set_user
       @user = User.find(params[:id])
    end
end

虽然我们可以使用rescue_from ActiveRecord::RecordNotFound, with: :record_not_found - 我们甚至不知道实际上是对失败用户的查询!例如,它可能是ApplicationController中上游定义的其他一些回调。

此外,当无法找到资源时,您的应用程序应通过发送404 - NOT FOUND410 - GONE响应来告知客户端。不是通过重定向,因为它发送一个3xx响应代码,表明资源已暂时移动。

您可以直接在回调中解救异常:

    def set_user
       begin 
         @user = User.find(params[:id])
       rescue ActiveRecord::RecordNotFound
         @users = User.all
         flash.now[:error] = "User not found"
         # note that we render - not redirect!
         render :index, status: 404
       end
    end

虽然在大多数情况下最好将其保留为默认处理程序,而不是捏破应用程序的REST界面并添加一堆复杂性。

答案 1 :(得分:0)

- 更新 -

可能将其放入

private

def problem
  begin
    @user = User.find(params[:id])
  rescue ActiveRecord::RecordNotFound
    redirect_to user_path, error: "Sorry, no user found."
  end
end

并有一个before_action

before_action :problem, except: [:new, :edit]

这个问题也可以帮助rescue from ActiveRecord::RecordNotFound in Rails

答案 2 :(得分:0)

解决方案A,使用定义此before_filter的公共父控制器,如:

class RescueNotRoundRecordController < ApplicationController
  rescue_from ActiveRecord::RecordNotFound, with: :record_not_found

  private
  def record_not_found
    redirect_to user_path, error: "Sorry, no user found."
  end 
end

class UserController < RescueNotRoundRecordController
  before_action :get_user
end

解决方案B,使用模块来做到这一点,我认为这是更好的方法:

module RescueNotRoundRecord
  def self.included(mod)
    mod.class_eval do
      rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
    end
  end

  private
  def record_not_found
    redirect_to user_path, error: "Sorry, no user found."
  end 
end

class UserController < ApplicationController
  include RescueNotRoundRecord
end

答案 3 :(得分:0)

我看到了最明显的两种变体来解决通过操作名称过滤器呈现错误的问题:

rescue_from Exception, with: ->(e) { %w(new edit).include?(action_name) && method(:record_not_found)[e] }

rescue_from Exception do |e|
   %w(new edit).include?(action_name) && method(:record_not_found)[e]
end