'How to use Simple Form and Direct Upload ActiveStorage

I'm having a trouble when I try to use Simple Form gem for upload video. I'm using ActiveStorage and local storage for this. My form looks like this:

= simple_form_for @film do |f|
  = f.error_notification
  = f.input :title, as: :string
  = f.input :description, as: :string
  = f.input :cover_img, as: :file

  = f.input :film_link, as: :file, direct_upload: true
  = f.button :submit
  = link_to 'back', :back, class: 'btn btn-secondary'

I've followed instruction on here https://edgeguides.rubyonrails.org/active_storage_overview.html So I've included js and css files in my app. But that won't work. It looks like there's some troubles with passing direct_upload: true via simple_form. I've also find article https://phase2online.com/blog/2018/10/03/easily-upload-files-with-active-storage-in-rails-5-2/ and pull git repo from here

An this works on when you'll use form_for on your _form. When I change form to use simple_form gem(instead of form_form use simple_form_for) it won't work.

Anyone have an idea why this is not working please? I use ruby 2.6.3 and Rails 5.2.3 and simple_form (5.0.1)



Solution 1:[1]

There're is the way to make this work.

  1. We can change f.input to f.file_field as hashrocket suggest - but then validation of simple form will not work, and perhaps we have to add class to this input plus extra div before.
  2. We can add html attribute to the f.input.

For me this is working I hope it will help someone else too.

= simple_form_for @film do |f|
  = f.error_notification
  = f.input :title, as: :string
  = f.input :description, as: :string
  = f.input :cover_img, as: :file, input_html: { data: { direct_upload_url: '/rails/active_storage/direct_uploads' } }
  = f.input :film_link, as: :file, input_html: { data: { direct_upload_url: '/rails/active_storage/direct_uploads' } }
  = f.button :submit
  = link_to 'back', :back, class: 'btn btn-secondary'

Solution 2:[2]

I would suggest to simply add a custom input for that to avoid repetition within your view files. Put this in the file app/inputs/direct_upload_file_input.rb:

# frozen_string_literal: true
class DirectUploadFileInput < SimpleForm::Inputs::FileInput
  def input_html_options
    super.merge({ direct_upload: true })
  end
end

Solution 3:[3]

These days (rails 6.x), you shouldn't need to specify as: file (simple form should figure this out via reflection) and you can just pass direct_upload: true to input_html:

= simple_form_for @film do |f|
  = f.error_notification
  = f.input :title, as: :string
  = f.input :description, as: :string
  = f.input :cover_img, input_html: { direct_upload: true }
  = f.input :film_link, input_html: { direct_upload: true }
  = f.button :submit
  = link_to 'back', :back, class: 'btn btn-secondary'

Verify it's doing the right thing by looking at the generated html. You should see an attribute like this on each input which is of type="file":

data-direct-upload-url="https://<your app server>/rails/active_storage/direct_uploads"

@anka's suggestion to create a custom input type is a good one, but you could also edit the default simple form wrappers for file types if you know all your files will be direct uploads to S3.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 nikos83
Solution 2 anka
Solution 3 James H