代码之家  ›  专栏  ›  技术社区  ›  Syntactic Fructose

如何简化轨道中的大响应块

  •  2
  • Syntactic Fructose  · 技术社区  · 5 年前

    有人建议我如何减少 respond_to 阻碍?我的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
    
    1 回复  |  直到 5 年前
        1
  •  2
  •   tadman    5 年前

    如果你在做 对于JSON响应,就像您正在构建一个JSON API,那么创建一个方法来简化该模式是有意义的。例如,创建如下方法:

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

    它与您建立的结构一起工作,并使用它生成正确的 render

    这取决于将内部代码映射到Rails响应代码:

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

    symbol codes 帮助代码变得更容易解释。

    另一个需要注意的是您的订单验证可以提取到 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
    

    如果该处理程序呈现某个内容,则链将在请求被视为已服务时停止。

    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
    

    我用过 save! 在这里这样 路径简单得多,没有分支。发生错误时 然后

    考虑添加 为了验证请求者是否需要JSON并在那里处理它,而不是在大量的 respond_to 调用控制器操作。

    别忘了 rescue_from