Rails 6: CSV возвращается в полезной нагрузке ответа, но не загружается

#ruby-on-rails #ruby-on-rails-6

Вопрос:

У меня есть представление, которое позволяет пользователю выбрать группу записей для экспорта в файл CSV.

После того, как пользователь выберет набор записей и отправит форму с информацией, CSV будет правильно сгенерирован и возвращен, но вместо того, чтобы спросить пользователя, где сохранить файл, ничего не произойдет. После проверки запроса в браузере я обнаружил, что данные присутствуют в полезной нагрузке ответа в виде необработанного CSV. Как я могу заставить браузер вместо этого показывать диалоговое окно сохранения?


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

 <%= form_with url: export_to_csv_admin_properties_url, multipart: true do |form| %>
  <table class="table is-striped">
    <thead>
      <tr>
          <th><%= sortable "id" %></th>
          <th><%= sortable "city" %></th>
          <th>To export</th>
      </tr>
    </thead>

    <tbody>
      <% @properties.each do |property| %>
      <tr>
        <td><%= property.id %></td>
        <td> <%= property.city %> </td>
        <td><%= check_box("export", property.id) %></td>
      </tr>
      <% end %>
    </tbody>
  </table>

  <%= form.submit "Export" %>
<% end %>
 

Контроллер правильно получает данные и вызывает класс, ответственный за построение строки CSV:

 def export_to_csv
  ids_to_export = params[:export].select { |_key, value| value == '1' }.keys
  properties = Property.find(ids_to_export)
  csv_data = CsvService.export_properties(properties)

  send_data csv_data, filename: "exported_properties.csv", type: 'text/csv'
end
 

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

1. @dbugger — csv_data это строка, у которой нет #read метода. Каков второй параметр, a ?

2. Если вы используете send_data для возврата файл, который вы хотите загрузить с помощью браузера, вы, вероятно, захотите добавить disposition: 'attachment; filename=exported_properties.csv' или что-то подобное, согласно документам. Кроме того, вы должны выполнять свою send_data работу в контроллере, а не в своем классе. Верните данные CSV из класса и отправьте их пользователю в контроллере.

3. @JohnP, он автоматически определяет расположение с этими значениями. Заголовок ответа содержит Content-Disposition attachment; filename="exported_properties.csv"; filename*=UTF-8''exported_properties.csv . send_data находится у контроллера.

4. Значит export_to_csv , метод находится в контроллере? Документы , вероятно, лучшее место для поиска информации о том, как это работает. Там даже есть пример кода для CSV-файла. В более общем плане, однако, если ответ доходит до браузера, но не отображается, это, вероятно, проблема с заголовками — рельсы не передают информацию, необходимую браузеру, чтобы знать, что делать с данными, поэтому вам нужно убедиться, что вы предоставляете ее send_data , правильно позвонив. Хотя, боюсь, я больше ничего не могу с собой поделать!

Ответ №1:

Добавление local: true from_with метода в представление решает проблему.

 <%= form_with url: export_to_csv_admin_properties_url, local: true do |form| %>