Rails 6 Active Storage: не удалось найти или построить blob: ожидалось присоединение, получено ноль

Только что создано новое приложение Rails 6, и я пытаюсь разрешить добавление изображений в blob-объект active_storage вместо их замены через форму, созданную с помощью rails scaffold.

Следовал документации (https://guides.rubyonrails.org/active_storage_overview.html#has-many-attached), используя #attach в моем контроллере, но это приводит к странице с ошибкой и сохраняет поведение «по умолчанию», заключающееся в замене всех изображений вместо добавления новых изображений.

Использование Rails 6.0.0 с active_storage 6.0.0

Сначала я создал модель страницы, используя rails g scaffold Page name:string, а затем добавил в свою модель page.rb связь с ActiveStorage has_many_attached :images

В своей форме я добавил поле file_field, разрешающее несколько загрузок:

<%= form.file_field :images, multiple: true %>

Вот мое действие по обновлению контроллера, обратите внимание, @page.images.attach(params[:images]), которое, согласно документации, должно выполнять эту работу.


def update

    respond_to do |format|
      if @page.update(page_params)

        @page.images.attach(params[:images])

        format.html { redirect_to site_pages_path(@site), notice: 'Page was successfully updated.' }
        format.json { render :show, status: :ok, location: @page }
      else
        format.html { render :edit }
        format.json { render json: @page.errors, status: :unprocessable_entity }
      end
    end
  end

При заполнении формы, прикреплении новых картинок и публикации я получил следующую ошибку:

ArgumentError in PagesController#update
Could not find or build blob: expected attachable, got nil 

Указывая линию @page.images.attach(params[:images])

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


person Simon Mo    schedule 08.10.2019    source источник
comment
Сколько изображений вы пытаетесь прикрепить? Если в параметрах несколько, вам нужно будет перебрать их и прикрепить по отдельности.   -  person Mark    schedule 08.10.2019
comment
Привет, Марк, я попытался прикрепить 2 или 3 изображения для тестирования, он должен принимать любое количество изображений. Вы имеете в виду, что я должен сделать что-то вроде цикла внутри контроллера, перебирая все вложения и прикрепляя их по отдельности? например params[:images].each do |image|?   -  person Simon Mo    schedule 08.10.2019
comment
Пробовал следующее: params[:page][:images].each do |image| @page.images.attach(image) end Ошибок больше нет, но старые картинки все равно удаляются, а новые прикрепляются 2 раза! (потому что я тестировал с двумя изображениями)   -  person Simon Mo    schedule 08.10.2019
comment
Да, это то, о чем я подумал - я понятия не имею, почему ваше исходное изображение перезаписывается :(   -  person Mark    schedule 08.10.2019
comment
Я думаю, что это, возможно, исходит из оригинального if @page.update(page_params), сгенерированного rails scaffold, я слышал, что обновление фактически заменяет изображение по умолчанию в Rails 6. Может быть, мне следует перейти к чему-то более индивидуальному, чем использование сгенерированного действия.   -  person Simon Mo    schedule 08.10.2019
comment
Ах, хорошее место - если это так, вы можете удалить параметры изображений из page_params (возможно, def page_params_without_images), использовать это для обновления, а затем продолжить, как вы   -  person Mark    schedule 08.10.2019
comment
@Mark спасибо за помощь! может исправить проблему, опубликовал свое решение ниже;)   -  person Simon Mo    schedule 08.10.2019
comment
Рад, что ты туда попал :)   -  person Mark    schedule 08.10.2019


Ответы (2)


В Rails 6 поведение по умолчанию для has_many_attached было изменено с Rails 5. Ранее файлы добавлялись к списку вложений, а не заменялись.

К счастью, это значение по умолчанию можно изменить в файле application.rb:

config.active_storage.replace_on_assign_to_many = false

Затем вы можете оставить раздел images: [] в разрешенном списке и полностью удалить вызов @page.images.attach(params[:images]).

person user10704464    schedule 08.10.2019
comment
Боже, спасибо за это! Я строю обходной путь для этого в течение часа. почему это не задокументировано в ActiveStorageGuide: / где я могу найти эту информацию? - person larz; 29.12.2019
comment
Он находится под активным хранилищем, заметные изменения в примечаниях к выпуску rails 6. edgeguides.rubyonrails.org/ - person user10704464; 31.12.2019

Хорошо, я могу исправить проблему!

Проблема: действие update заменит все картинки.

Итак, вот что я сделал:

1) Я удалил images: [] из разрешенного списка (строгие параметры)

2) Я написал этот код, чтобы прикрепить каждое новое изображение по отдельности и поместить его в действия create и update:

    if params[:page][:images].present?
      params[:page][:images].each do |image|
        @page.images.attach(image)
      end
    end

#attach фактически разрешит параметр.

Не уверен, что это был лучший способ, но теперь он работает

person Simon Mo    schedule 08.10.2019