Как упростить большие блоки response_to в Rails - PullRequest
2 голосов
/ 01 марта 2020

У кого-нибудь есть рекомендации, как можно уменьшить respond_to блоки? Кажется, мое JSON форматирование занимает много места. Контроллер, по большей части, отвечает HTML, но этот конкретный c метод вызывается через 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 Ответ

3 голосов
/ 01 марта 2020

Если вы выполняете ответы lot из JSON, как, например, вы создаете JSON API, то имеет смысл создать метод, упрощающий этот шаблон. Например, создайте метод, подобный следующему:

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

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

Где это работает с созданной вами структурой и использует ее для генерации правильного вызова render. Поскольку это работает только с данными, структурированными определенным образом c, это помогает обеспечить согласованность ваших ответов.

Это зависит от сопоставления внутренних кодов с кодами ответов Rails:

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

Там, где использование кодов символов помогает коду стать более понятным.

Еще одна вещь, которую стоит отметить, - проверка вашего заказа может быть извлечена в обработчик 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!, поэтому путь ожидаемый намного проще, разветвления нет. Если / когда возникает ошибка , тогда вы можете go отключить в область обработки исключений.

Рассмотрите возможность добавления before_action, чтобы подтвердить, что запрашивающий запрос хочет JSON и обработать его там вместо того, чтобы заглушать много-много вызовов respond_to в действиях вашего контроллера.

Не забывайте о rescue_from, который может спасти от распространенных проблем, таких как недопустимые типы запросов и так далее. Это также может уменьшить количество повторяющегося кода, которое вам нужно сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...