управлять файлами через вложенные атрибуты, передаваемые params в запросе PUT на API rails - PullRequest
0 голосов
/ 14 февраля 2020

Мне нужно управлять файлами, прикрепленными к модели, через вложенные атрибуты. Основная проблема заключается в том, что в запросе возникают проблемы с синтаксическим анализом параметров ha sh, и он объединяет некоторые из этих параметров вместе.

Модель следующая:

class Logging::Note < ApplicationRecord
  belongs_to :user

  has_many :uploads, class_name: 'Logging::NoteUpload',
                     foreign_key: 'logging_note_id', inverse_of: :note, dependent: :destroy

  accepts_nested_attributes_for :uploads, allow_destroy: true
end

это контроллер:

class API::V1::Logging::NotesController < API::V1::APIController
  def update
    authorize note

    note.update(note_update_params) ? render_note : render_note_errors
  end

  private

  def note_update_params
    params.require(:note).permit(:text, :date, :title,
                                 uploads_attributes: [:id, :_destroy, file: []])
  end
end

, и я использую rspe c для его проверки:

  context 'when the user is logged in' do
  subject(:put_request) do
    put api_note_path(note.id), params: params, headers: auth_headers_with_group
  end

  let(:note) { create(:logging_note, user: author) }
  let!(:note_upload) { create(:logging_note_upload, note: note) }
  let!(:note_upload2) { create(:logging_note_upload, note: note) }

  let(:params) do
    {
      note: {
        text: new_text,
        date: new_date,
        title: new_title,
        uploads_attributes: uploads_attributes
      }
    }
  end

  let(:uploads_attributes) do
    [
      {
        id: note_upload.id,
        _destroy: true
      },
      {
        id: note_upload2.id,
        _destroy: true
      },
      {
        file: [test_picture('sample_graph.png')]
      }
    ]
  end

  specify do
    put_request

    expect(response).to have_http_status(:success)
  end


  it 'updates the note record' do
    expect {
      put_request
    }.to change(Logging::NoteUpload, :count).by(1)

    expect(note.reload.text).to eq(new_text)
    expect(note.title).to eq(new_title)
    expect(note.date).to eq(new_date)
    expect(note.uploads).not_to include(note_upload, note_upload2)
    expect(note.reload.uploads.count).to eq(1)
  end
end

когда я устанавливаю эти параметры и при отладке в методе обновления контроллера, note_update_params [: uploads_attributes] .count должен возвращать 3, но вместо этого он возвращает 2.

note_update_params [ : uploads_attributes]:

[
<ActionController::Parameters {
  "id"=>"e1a437ff-42b4-4cb2-af6c-0edf0a824265", 
  "_destroy"=>"true"
} permitted: true>,

<ActionController::Parameters {
  "id"=>"a993722e-23c5-4e75-a755-aff4553201e3", 
  "_destroy"=>"true", 
  "file"=>[#<ActionDispatch::Http::UploadedFile:0x00007ff8a8099e00 @tempfile=# 
          <Tempfile:/var/folders/14/1rt4bsg94cj74_gc631xjnmm0000gn/T/RackMultipart20200214- 
          18920-1lmntho.png>, @original_filename="sample_graph.png", @content_type="image/png", 
          @headers="Content-Disposition: form-data; name=\"note[uploads_attributes][][file][]\"; 
          filename=\"sample_graph.png\"\r\nContent-Type: image/png\r\nContent-Length: 
          51604\r\n">]
} permitted: true>
]

он получает ключи следующих параметров:

["id", "_destroy"]
["id", "_destroy", "file"]

, когда должен получить следующее:

["id", "_destroy"]
["id", "_destroy"]
["file"]

, как описывает этот поток https://github.com/rails/rails/issues/23997 добавление как:: json к запросу должно решить проблему синтаксического анализа, но json не обрабатывает файлы, поэтому вместо этого контроллер получает пустой параметр.

["id", "_destroy"]
["id", "_destroy"]
[]
...