修复红宝石中的重复方法

时间:2018-07-22 01:40:38

标签: ruby-on-rails ruby refactoring styling

我正在用ruby在Rails上编写一个API,我发现我的方法非常重复。这就是我几乎所有方法的样子。它们都遵循相似的结构。我只是抓住了我的一种方法,并将其放在这里:

def create
  if current_user

    @object = Object.new(object_params)

    if @object.save
      render json: {
        status:  "SUCCESS",
        message: "object saved"
      }, status: :ok
    else
      render json: {
        status: "ERROR",
        message: "Could not save object"
      }, status: :unprocessable_entity
    end
  else
    render json: {
      status: "UNAUTHORIZED"
    }, status: :unauthorized
  end
end

当然,不是我的所有方法都可以创建和保存对象。但是它们都遵循类似的模式。首先,我检查current_user是否不为零。如果是,我将呈现JSON响应:

if current_user
  # do something
else
  render json: {
    status: "UNAUTHORIZED"
  }

如果找到当前用户,并且无论该方法必须运行成功,那么我将呈现另一个JSON响应:

if everything_went_well
  render json: {
    status: "SUCCESS",
    message: "Everything went ok!"
  }
else
  render json: {
    status: "ERROR",
    message: "There was a problem!"
  }
end

我很确定有一种抽象这种功能的方法。我在网上查找了一些有用的提示,但这些提示对项目的其他部分(例如模型和视图)有所帮助。但是,我在网上看到的大多数技巧都不太适合我控制器中的代码。

2 个答案:

答案 0 :(得分:2)

您可以为此使用before_filter。请注意,当before_action已经呈现视图时,该动作本身将不再被调用。

before_action :check_permission

def create
  @object = Object.new(object_params)

  if @object.save
    render json: {
      status:  "SUCCESS",
      message: "object saved"
    }, status: :ok
  else
    render json: {
      status: "ERROR",
      message: "Could not save object"
    }, status: :unprocessable_entity
  end
end

private 

def check_permission
  return if current_user

  render json: {
    status: "UNAUTHORIZED"
  }, status: :unauthorized
end

答案 1 :(得分:0)

如果所有控制器看起来都是这样,那么您可以拥有一个基本控制器,并使所有其他控制器都从该控制器继承。这将使您的代码为DRY

因此,您的基本控制器将如下所示:

class API::BaseController < ApplicationController
  protected

  def check_permission
    return if current_user

    render json: {
      status: "UNAUTHORIZED"
    }, status: :unauthorized
  end

  def render_success
    render json: {
      status:  "SUCCESS",
      message: "object saved"
    }, status: :ok
  end

  def render_error
    render json: {
      status: "ERROR",
      message: "Could not save object"
    }, status: :unprocessable_entity
  end
end

然后在您的一个控制器中:

class API::OtherController < API::BaseController
  before_filter :check_permission

  def create
    @object = Object.new(object_params)

    if @object.save
      render_success
    else
      render_error
    end
  end
end

您也可以将before_filter部分移到基本控制器上,但是灵活性较差。在当前设置下,您只能针对某些操作(例如before_filter :check_permission, only: [:create])使用该过滤器。

但是如果将before_filter移至基本控制器,则会失去灵活性。