2

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">
ThorTL67
  • 528
  • 4
  • 13
  • Have you checked the form markup? Can you verify that the form attribute actually has a `data-remote="true"` on it? – NM Pennypacker Nov 07 '18 at 14:29
  • Yep, added this in to my post. Just to add - this form worked perfectly before I added active storage into it. – ThorTL67 Nov 07 '18 at 14:32
  • Your form is using the POST method. Try adding `method: :patch` to your `form_for` tag – NM Pennypacker Nov 07 '18 at 16:21
  • Can you remove `remote: true` at submit button and try again? And when set remote to true at your form, it always runs to update.js.erb file. No need to format.js do ... – Dapeng114 Nov 08 '18 at 08:40
  • @NMPennypacker - Adding `method: :patch` in still results in `method="post"` in the form markup. Changing this to `method="patch"` in my browser causes the form to try an submit to the show action! @Dapeng114 - Removing remote: true from the submit button had the same result unfortunately. Thanks for the tip on the format.js ! – ThorTL67 Nov 08 '18 at 10:09

2 Answers2

0

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.

ThorTL67
  • 528
  • 4
  • 13
0

Also transiting to Active Storage and stuck here. But (I recalled that) in my previous implementation, where I used github/jQuery-File-Upload I solved (as it turns out) the same problem:

Rails.fire($("#form_id")[0], 'submit');

This is a rails-ujs method I got rom this Q/A: /with-rails-ujs-how-to-submit-a-remote-form-from-a-function

As I get now all it goes from the fact that:

The event — submit — is not raised when calling the form.submit() method directly, — MDN:
https://developer.mozilla.org/en-US/docs/Web/Events/submit
https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript

Denis
  • 940
  • 12
  • 16