Проверка модели Rails на стороне сервера в форме React - PullRequest
0 голосов
/ 06 августа 2020

Я пытаюсь проверить вводимые пользователем данные на стороне сервера в приложении Rails с React as view. Обычно я делаю вызовы ax ios Rails API следующим образом:

const Script = props => {
  const [script, setScript] = useState({})
  const [scene, setScene] = useState({})
  const [loaded, setLoaded] = useState(false)

  useEffect(() => {
    const scriptID = props.match.params.id
    const url = `/api/v1/scripts/${scriptID}`

    axios.get(url)
    .then( resp => {
      setScript(resp.data)
      setLoaded(true)
    })
    .catch(resp => console.log(resp))

  }, [])

  const handleChange = (e) => {
    e.preventDefault()
    setScene(Object.assign({}, scene, {[e.target.name]: e.target.value}))
  }

  const handleSubmit = (e) => {
    e.preventDefault()

    const csrfToken = document.querySelector('[name=csrf-token]').content
    axios.defaults.headers.common['X-CSRF-TOKEN'] = csrfToken

    const script_id = script.data.id
    axios.post('/api/v1/scenes', {scene, script_id})
    .then(resp => {
      const included = [...script.included, resp.data.data]
      setScript({...script, included})
    })
    .catch(err => {
      console.log(err.response.data.error)
    })
    .finally(() => {
      setScene({name: '', description: ''})
    })

  }

Все данные передаются в компонент реакции с формой.

  return (
    <div className="wrapper">
      {
        loaded &&
          <Fragment>
            .
            .
            .
            <SceneForm
              handleChange={handleChange}
              handleSubmit={handleSubmit}
              attributes={script.data.attributes}
              scene={scene}
            />
          </Fragment>
      }
    </div>
  )

В этой форме у меня есть поле имени и соответствующее имя в Rails имеют уникальность проверки: true. все работает нормально, если я ввожу действительное (уникальное) имя.

Я попытался выполнить проверку, но результат меня не удовлетворил. (Это работает в целом: мой метод no_errors? выполняет то, что должен делать, и я получаю статус 403) Это часть контроллера:

  def create
    scene = script.scenes.new(scene_params)
    if no_error?(scene)
      if scene.save
        render json: SceneSerializer.new(scene).serialized_json
      else
        render json: { error: scene.errors.messages }, status: 422
        # render json: { error: scene.errors.messages[:name] }, status: 423
      end
    else
      render json: { error: "name must be unique" }, status: 403
    end
  end

.
.
.

  private

  def no_error?(scene)
    Scene.where(name: scene.name, script_id: scene.script_id).empty?
  end

Если я ввожу существующее имя, я получаю консоль .log следующим образом:

скриншот

Вот что меня беспокоит: я не доволен своим подходом к обработке ошибок в целом. Я не хочу, чтобы сообщение 403 регистрировалось в консоли (в первую очередь я хочу избежать этого сообщения). Моя идея состоит в том, чтобы использовать подход «простой формы»: сделать границу моего поля красной и опубликовать сообщение об ошибке под полем, без вывода на консоль ... И еще одно примечание: правильный ли статус 403? Я думал о 422, но не был уверен ...

Заранее спасибо за идеи!

1 Ответ

0 голосов
/ 06 августа 2020

403 - неправильный код статуса. Вам нужно вернуть 422 (unprocessable entity). 403 - это больше о политике и о том, что вам разрешено делать.

Затем, когда вы имеете дело с HTTP-запросом, стандартно печатать запрос и код состояния в консоли браузера. Не удивлюсь получить здесь вашу проблему. Если он собирается отобразить ошибку, вы можете просто использовать функцию, которая раскрашивает (или любой другой фейерверк) ваш ввод, если ответ кода состояния - 422.

...