Вернуть ошибки проверки гранита в формате JSON - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть модель Granite User с некоторыми проверками.Когда кто-то делает запрос POST на users/new, я бы хотел вернуть ошибки валидации (если есть) в виде JSON.В настоящее время у меня есть:

if user.errors.size > 0
  halt env, status_code: 500, response: user.errors.to_json
end

Но когда я пытаюсь скомпилировать, я получаю:

in /usr/local/Cellar/crystal/0.26.1/src/json/to_json.cr:66: no overload 
matches 'Granite::Error#to_json' with type JSON::Builder
Overloads are:
- Object#to_json(io : IO)
- Object#to_json()

  each &.to_json(json)
         ^~~~~~~

1 Ответ

0 голосов
/ 16 сентября 2018

Таким образом, проблема в том, что User#errors является Array(Granite::Error), то есть Array, удерживающим Granite::Error s.К сожалению, не похоже, что Granite::Error реализует метод to_json(JSON::Builder) (т. Е. Метод to_json, принимающий параметр типа JSON::Builder), на который опирается Array#to_json (тот фрагмент, который вы видите в реализациииз Array#to_json, который вы можете просмотреть на GitHub .).

Я бы порекомендовал создать JSON самостоятельно, используя JSON.build.Это имеет дополнительный побочный эффект, заключающийся в том, что JSON, с которым вы отвечаете (который, как я думаю, используется некоторым клиентом), полностью находится под вашим контролем.Если бы разработчики Granite изменили способ кодирования Granite::Error s в JSON, а вы использовали их метод to_json, это изменение ничего бы не подняло во время компиляции.

Как примечание,Я бы рекомендовал не использовать код состояния 500 для обозначения ошибки проверки, так как обычно она зарезервирована для непредвиденных ошибок, внутренних для вашего сервера.Ошибка 4xx (например, 400 - неверный запрос) была бы более подходящей.В качестве второго примечания было бы более RESTful, чтобы сделать POST до конечной точки /users, в отличие от /users/new.

С этими изменениями здесь будет получен фрагмент:

if user.errors.size > 0
  errors_as_json = JSON.build do |json|
    json.array do
      user.errors.each do |error|
        json.string error.to_s
      end
    end
  end
  halt env, status_code: 400, response: errors_as_json
end
...