【问题标题】:Rails pattern for action(update, delete, etc) & error checking用于操作(更新、删除等)和错误检查的 Rails 模式
【发布时间】:2014-05-04 17:35:42
【问题描述】:

我是 Rails 的新手,所以我想知道下面是否存在已知模式(我的 Google 技能在这里失败了)。

我所有的 Rest 控制器都遵循以下基本模式:

检查项目是否存在 --> 如果存在则获取项目 --> 如果不存在则返回错误 --> 如果存在则执行某些操作 --> 检查操作是否失败 --> 如果失败则返回错误--> 如果没有,则成功。所以两个动作,两个错误检查。我的问题是:这是一个很好的正确模式,还是我应该做一些不同的事情?

“销毁”方法示例:

def destroy 
  if @team = fetch_team
    if @team.destroy
      render json: {message: "team: '#{params[:id]}' deleted"}, status: 200
    else
      render json: {message: "error: #{@team.errors.full_messages}"}, status: 500
    end          
  else
    render json: {message: "team: '#{params[:id]}' not found"}, status: 404  
  end
end

##

def fetch_team
    Team.find_by(name: params[:id])
end

【问题讨论】:

    标签: ruby-on-rails ruby restful-url


    【解决方案1】:

    我会从单个操作中重构您的一些逻辑,使其更干燥。

    首先,我会将fetch_team 的检查移到before_action 过滤器中。这样一来,您就可以让 Rails 为多个操作运行它,例如 showupdatedestroy

    当你调用Team.find_by!(注意爆炸)时,如果没有找到记录,Rails 将抛出一个ActiveRecord::RecordNotFound 异常。因此,如果没有找到记录,您可以使用rescue_from 执行您需要执行的操作。这样一来,您就无需在多个操作中重复该逻辑。

    class TeamsController < ApplicationController
      before_action :find_team, only: [:show, :update, :destroy]
      rescue_from ActiveRecord::RecordNotFound, with: :not_found # This can be moved to `ApplicationController` if you follow this pattern in ALL of your controllers
    
      def destroy
        if @team.destroy
          render json: { message: "team: '#{params[:id]}' deleted" }, status: 200
        else
          render json: { message: "error: #{@team.errors.full_messages}" }, status: 500
        end
      end
    
    private
    
      def find_team
        @team = Team.find_by!(name: params[:id])
      end
    
      def not_found
        render json: { message: "team: '#{params[:id]}' not found" }, status: 404
      end
    end
    

    说了这么多,我觉得not_found中的定义是非常大方的。通常,当find_by! 失败时,我会让控制器抛出它自己的 404 异常,并期望客户端能够识别 404 标头并做出相应的响应。如果您希望显示示例中的错误消息,这取决于您。

    【讨论】:

    • 这看起来好多了,谢谢。但是似乎我需要ActiveRecord::RecordNotFound 而不是ActiveRecord::NotFound
    • 编辑了我的答案。你有证据证明我在浏览器中编码了整个答案。至少我是一致的。 :)
    【解决方案2】:

    让我们使用销毁操作示例:

    我见过的常见方法是让控制器销毁动作像这样简单:

    def destroy
      @team = Team.find(params[:id]) # first find the object you want to delete 
      @team.destroy # if it's found, call the destroy method on it. if it's not found, you won't get to this line. it'll raise error. 
      respond_to do |format|
        format.html { redirect_to teams_url } #this is redirecting to your chosen path once it's destroyed. 
        format.json { head :no_content }
      end
    end
    

    但在您看来,您将在继续删除之前为用户提供改变主意的机会:

    app/views/teams/show.html.erb

    <%= link_to 'Delete team', @team class: 'btn btn-primary', method: :delete, data: { confirm: 'Are you sure you want to delete this team?' } %>
    

    这将提示弹出消息。他们可以点击cancel或点击ok继续删除

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-10
      • 2021-09-10
      • 1970-01-01
      • 1970-01-01
      • 2013-10-08
      • 2015-11-12
      • 2023-03-23
      • 1970-01-01
      相关资源
      最近更新 更多