Мне нужно управлять файлами, прикрепленными к модели, через вложенные атрибуты. Основная проблема заключается в том, что в запросе возникают проблемы с синтаксическим анализом параметров 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"]
[]