After upgrading my app to Rails 5.2, I've found some time to look at Active Storage. Following the guide, I've installed it and ran the migrations necessary.
On my User model I want to attach an avatar as per the example here: Edge Guide for Active Storage
The error I am receiving upon submitting my form is ActionController::InvalidAuthenticityToken
<%= form_for @user, remote: true do |f| %>
<%# Other user fields redacted %>
<div class="form-group">
<%= f.label :avatar %>
<%= f.file_field :avatar %>
</div>
<%= f.submit "Save", remote: true %>
<% end %>
I changed the form_for to include authenticity_token: true
like this:
<%= form_for @user, remote: true, authenticity_token: true do |f| %>
This removed my authenticity error and inserted the file into my DB, however this has caused an Unknown format error, in that it is routing to my controller with html instead of js.
Logs:
Started PATCH "/users/22" for 127.0.0.1 at 2018-11-07 13:36:22 +0000
Processing by UsersController#update as HTML
Disk Storage (5.7ms) Uploaded file to key: aJQ3m2skk8zkHguqvhjV6tNk (checksum: 7w6T1YJX2LNIU9oPxG038w==)
ActiveStorage::Blob Create (23.6ms) INSERT INTO `active_storage_blobs` (`key`, `filename`, `content_type`, `metadata`, `byte_size`, `checksum`, `created_at`) VALUES ('aJQ3m2skk8zkHguqvhjV6tNk', 'Dq3gtJjU0AAbdIj.jpg-large.jpeg', 'image/jpeg', '{\"identified\":true}', 50642, '7w6T1YJX2LNIU9oPxG038w==', '2018-11-07 13:36:22')
ActiveStorage::Attachment Create (3.4ms) INSERT INTO `active_storage_attachments` (`name`, `record_type`, `record_id`, `blob_id`, `created_at`) VALUES ('avatar', 'User', 22, 1, '2018-11-07 13:36:22')
(9.4ms) ROLLBACK
Completed 406 Not Acceptable in 630ms (ActiveRecord: 93.1ms)
ActionController::UnknownFormat (ActionController::UnknownFormat):
Users#Update
def update
respond_to do |format|
if @user.update(user_params)
flash.now[:notice] = 'User saved successfully!'
format.js do
@users = User.all
end
else
flash.now[:alert] = @user.errors.full_messages.to_sentence
format.js do
@users = User.all
render layout: false, content_type: 'text/javascript'
end
end
end
end
Any ideas as to why it is being submitted as HTML instead of JS?
Edit: Form Markup
<form class="edit_user" id="edit_user_22" enctype="multipart/form-data" action="/users/22" accept-charset="UTF-8" data-remote="true" method="post">
After much trial & error, it took using the Direct Upload feature of Active Storage to allow this to work. Allow me to explain my findings:
remote: true, multipart: true
don't play well together. See this stack overflow post for more details. Essentially you need to use jQuery or a gem to submit files remotely.
Following this edgeguides post (direct uploads). It seems as though when you click on submit; direct upload will catch the submit event and submit the file directly to a cloud server (or local in my dev case). It will then use the reference of that image in the form submit, instead of submitting the actual image.
This hit my Users#update
using JS and successfully attached the Avatar.