简体   繁体   English

如何简化 Rails 中的大型响应块

[英]How to simplify large respond_to blocks in Rails

Does anyone have recommendations for how I can reduce respond_to blocks?有没有人对我如何减少respond_to块有什么建议? It seems like my JSON formatting takes up a considerable amount of space.看起来我的 JSON 格式占用了大量空间。 The controller, for the most part, responds with HTML but this specific method is called via Ajax and responds in JSON:大多数情况下,控制器以 HTML 响应,但此特定方法通过 Ajax 调用并以 JSON 响应:

def create
  # initial setup

  respond_to do |format|
    unless paid_cash == true || PayPalPayments::OrderValidator.call(order_id)
      format.json do
        render json: {
          status: :unhandled_error,
          message: 'Invalid order ID supplied?'
        }, status: 400
      end
    end

    if @submitted_application.save(context: :create)
      MembershipMailer.with(application: @submitted_application).signup_confirmation.deliver_later

      format.json do
        render json: {
          status: :created,
          modal: render_to_string(
            partial: 'membership_confirmation_modal.html.erb'
          )
        }
      end
    else
      format.json do
        render json: {
          status: :validation_errors,
          errors: @submitted_application.errors
        }, status: 400
      end
    end
  end
end

If you're doing a lot of JSON responses, like you're building a JSON API, then it would make sense to make a method to simplify that pattern.如果您正在执行大量JSON 响应,例如您正在构建 JSON API,那么制定一种方法来简化该模式是有意义的。 For example, create a method like this:例如,创建一个这样的方法:

def respond_json(content)
  status = content[:status]

  render(
    json: content,
    status: STATUS_CODE_REMAPPED[status] || status
  )
end

Where that works with the structure you've established and uses it to generate the correct render call.它适用于您建立的结构并使用它来生成正确的render调用。 As this only works with data structured a specific way, it helps enforce consistency in your responses.由于这仅适用于以特定方式构建的数据,因此它有助于增强响应的一致性。

This depends on mapping the internal codes to the Rails response codes:这取决于将内部代码映射到 Rails 响应代码:

STATUS_CODE_REMAPPED = {
  created: :ok,
  unhandled_error: :bad_request,
  validation_errors: :bad_request
}

Where using the symbol codes helps the code become more self-explanatory.使用符号代码有助于代码变得更加不言自明。

Another thing to note is your order verification could be extracted into a before_action handler:要注意的另一件事是您的订单验证可以提取到before_action处理程序中:

before_action :verify_order_id, only: [ :create ]

def verify_order_id
  return if paid_cash || PayPalPayments::OrderValidator.call(order_id)

  respond_json(
    status: :unhandled_error,
    message: 'Invalid order ID supplied?'
  )
end

Where if that handler renders something the chain stops as the request is considered serviced.如果该处理程序呈现某些内容,则该链将在请求被视为已服务时停止。

This dramatically reduces how much code is left in the controller action:这大大减少了控制器操作中剩余的代码量:

def create
  @submitted_application.save!(context: :create)

  MembershipMailer.with(application: @submitted_application).signup_confirmation.deliver_later

  respond_json(
    status: :created,
    modal: render_to_string(
      partial: 'membership_confirmation_modal.html.erb'
    )
  )

rescue ActiveRecord::RecordInvalid
  respond_json(
    status: :validation_errors,
    errors: @submitted_application.errors
  )
end

I've used save!我用过save! here so that the expected path is much simpler, there's no branching.在这里,预期的路径要简单得多,没有分支。 If/when an error occurs then you can go off into the exception handling area.如果/当发生错误,那么你可以去扎进异常处理区。

Consider adding a before_action to validate that the requestor wants JSON and handle it there instead of stubbing in lots and lots of respond_to calls in your controller actions.考虑添加一个before_action来验证请求者想要 JSON 并在那里处理它,而不是在控制器操作中存根大量的respond_to调用。

Don't forget about rescue_from which can blanket rescue from common problems like invalid request types and so on.不要忘记rescue_from ,它可以从常见问题(如无效请求类型等)中进行全面救援。 This can also reduce how much repetitive code you have to do.这还可以减少您必须执行的重复代码量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM