Как отправить данные составной формы из js в Rails?

#javascript #ruby-on-rails #fetch #multipartform-data

Вопрос:

Вот как я тестирую свой контроллер, просто чтобы показать, какая структура запросов работает:

 post(
  :create,
  params: {
    play_session: {
      comment: "COMMENT",
      time_in_minutes: 10,
      video: fixture_file_upload("video.webm")
    }
  }
)
 

Я пытаюсь достичь этой конечной точки из JS с помощью этого:

 async function uploadFile(blob) {
  let play_session = { comment: "SUPER GOOD COMMENT", time_in_minutes: 23, video: blob };
  let formData = new FormData();
  formData.append("play_session", play_session);

  try {
    let response =
      await fetch(
        "http://localhost:3000/front/play_sessions",
        {
          method: "POST",
          body: formData
        }
      );

    console.log("HTTP response:", response);
  } catch(e) {
    console.log("Huston we have problem...:", e);
  }
}
 

Но я получаю эту ошибку в консоли Rails:

 Started POST "/front/play_sessions" for ::1 at 2021-09-24 22:00:30  0200
Processing by Front::PlaySessionsController#create as */*
  Parameters: {"play_session"=>"[object Object]"}
Completed 500 Internal Server Error in 3ms (Allocations: 1717)

NoMethodError (undefined method `permit' for "[object Object]":String):
 

Я попытался добавить заголовки к fetch вызову следующим образом:

 await fetch(
  "http://localhost:3000/front/play_sessions",
  {
    method: "POST",
    headers: {
      "Accept": "application/json",
      "Content-Type": "multipart/form-data"
    },
    body: formData
  }
);
 

Затем у меня возникла эта ошибка в консоли Rails:

 Started POST "/front/play_sessions" for ::1 at 2021-09-24 22:02:59  0200
Processing by Front::PlaySessionsController#create as JSON
  Parameters: {"------WebKitFormBoundaryESNX0mluVZ8VIiryrnContent-Disposition: form-data; name"=>""play_session"rnrn[object Object]rn------WebKitFormBoundaryESNX0mluVZ8VIiry--rn"}
Completed 400 Bad Request in 1ms (Allocations: 520)


ActionController::ParameterMissing (param is missing or the value is empty: play_session
Did you mean?  ------WebKitFormBoundaryESNX0mluVZ8VIiry
Content-Disposition: form-data; name
              action
              controller):
 

Комментарии:

1. Приложение FormData ожидает значение в виде строки или файла. Попробуйте добавить хэш один за другим, как formData.append('play_session[comment]', 'super good comment) . Я опубликую ответ, если это сработает 🙂

2. @разванс бах! в мишени ;). это работает, вы можете опубликовать ответ

Ответ №1:

Приложение FormData принимает name value пары , в которых value может быть либо строка, либо большой двоичный объект.

ценность

Значение поля. Это может быть строка USV или большой двоичный объект (включая подклассы, такие как файл). Если ни один из них не указан, значение преобразуется в строку.

Здесь formData.append("play_session", play_session) вы назначаете объект.

Поскольку Rails позволяет создавать хэши и массивы в парах, вам нужно добавлять параметры по play_session одному:

 let formData = new FormData();
formData.append('play_session[comment]', 'SUPER GOOD COMMENT')
formData.append('play_session[time_in_minutes]', 23)
formData.append('play_session', blob)
 

Для вложенных атрибутов вы должны сделать:

 formData.append('play_session[user_attributes][name]', 'Jack');
 

Для Массивов:

 formData.append('play_session[user_ids][]', "1");
formData.append('play_session[user_ids][]', "2");