Skip to content

Commit

Permalink
Add support for ActiveStorage direct uploads
Browse files Browse the repository at this point in the history
Closes #3296
  • Loading branch information
mshibuya committed Jul 30, 2022
1 parent ec83444 commit 22b4973
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 18 deletions.
2 changes: 1 addition & 1 deletion app/views/rails_admin/main/_form_file_upload.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<% if value = field.pretty_value %>
<%= value %>
<% end %>
<%= form.file_field(field.name, field.html_attributes.reverse_merge({ data: { fileupload: true }})) %>
<%= form.file_field(field.name, {data: {fileupload: true}}.deep_merge(field.html_attributes)) %>
</div>
<% if field.optional? && field.errors.blank? && file && field.delete_method %>
<a class="btn btn-info btn-remove-image" data-toggle="button" href="#" role="button">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<% end %>
</div>
<% end %>
<%= form.file_field(field.name, field.html_attributes.reverse_merge({ data: { :"multiple-fileupload" => true }, multiple: true })) %>
<%= form.file_field(field.name, { data: { :"multiple-fileupload" => true }, multiple: true }.deep_merge(field.html_attributes)) %>
<% if field.cache_method %>
<%= form.hidden_field(field.cache_method) %>
<% end %>
12 changes: 12 additions & 0 deletions lib/rails_admin/config/fields/types/active_storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ class ActiveStorage < RailsAdmin::Config::Fields::Types::FileUpload
{"#{name}_attachment": :blob}
end

register_instance_option :direct? do
false
end

register_instance_option :html_attributes do
{
required: required? && !value.present?,
}.merge(
direct? && {data: {direct_upload_url: bindings[:view].main_app.rails_direct_uploads_url}} || {},
)
end

def resource_url(thumb = false)
return nil unless value

Expand Down
12 changes: 12 additions & 0 deletions lib/rails_admin/config/fields/types/multiple_active_storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ def resource_url(thumb = false)
register_instance_option :eager_load do
{"#{name}_attachments": :blob}
end

register_instance_option :direct? do
false
end

register_instance_option :html_attributes do
{
required: required? && !value.present?,
}.merge(
direct? && {data: {direct_upload_url: bindings[:view].main_app.rails_direct_uploads_url}} || {},
)
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<% if defined?(ActiveStorage) %>
//= require activestorage
<% end %>
2 changes: 2 additions & 0 deletions spec/dummy_app/app/javascript/rails_admin.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
import "rails_admin/src/rails_admin/base";
import "flatpickr/dist/l10n/fr.js";
import * as ActiveStorage from "@rails/activestorage";
ActiveStorage.start();
1 change: 1 addition & 0 deletions spec/dummy_app/config/importmap.rails_admin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
pin '@hotwired/turbo-rails', to: 'https://ga.jspm.io/npm:@hotwired/turbo-rails@7.1.3/app/javascript/turbo/index.js'
pin '@popperjs/core', to: 'https://ga.jspm.io/npm:@popperjs/core@2.11.5/dist/esm/popper.js'
pin '@rails/actioncable/src', to: 'https://ga.jspm.io/npm:@rails/actioncable@7.0.2/src/index.js'
pin '@rails/activestorage', to: 'https://ga.jspm.io/npm:@rails/activestorage@7.0.3-1/app/assets/javascripts/activestorage.esm.js'
pin '@rails/ujs', to: 'https://ga.jspm.io/npm:@rails/ujs@6.1.4/lib/assets/compiled/rails-ujs.js'
pin 'bootstrap', to: 'https://ga.jspm.io/npm:bootstrap@5.1.3/dist/js/bootstrap.esm.js'
pin 'flatpickr', to: 'https://ga.jspm.io/npm:flatpickr@4.6.13/dist/flatpickr.js'
Expand Down
1 change: 1 addition & 0 deletions spec/dummy_app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"version": "0.1.0",
"dependencies": {
"@rails/webpacker": "5.4.3",
"@rails/activestorage": "^7.0.3-1",
"rails_admin": "file:../../",
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12"
Expand Down
34 changes: 34 additions & 0 deletions spec/integration/fields/active_storage_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe 'ActiveStorage field', type: :request, active_record: true do
subject { page }
let(:field_test) { FactoryBot.create :field_test }
before do
# To suppress 'SQLite3::BusyException: database is locked' exception
@original = page.driver.browser.url_blacklist # rubocop:disable Naming/InclusiveLanguage
page.driver.browser.url_blacklist = ['/rails/active_storage/representations'] # rubocop:disable Naming/InclusiveLanguage
end
after { page.driver.browser.url_blacklist = @original } # rubocop:disable Naming/InclusiveLanguage

describe 'direct upload', js: true do
before do
RailsAdmin.config FieldTest do
edit do
field(:active_storage_asset) { direct true }
end
end
end

it 'works' do
visit edit_path(model_name: 'field_test', id: field_test.id)
attach_file 'Active storage asset', file_path('test.jpg')
expect_any_instance_of(ActiveStorage::DirectUploadsController).to receive(:create).and_call_original
click_button 'Save'
expect(page).to have_content 'Field test successfully updated'
field_test.reload
expect(field_test.active_storage_asset.filename).to eq 'test.jpg'
end
end
end
23 changes: 22 additions & 1 deletion spec/integration/fields/multiple_active_storage_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
end
# To suppress 'SQLite3::BusyException: database is locked' exception
@original = page.driver.browser.url_blacklist # rubocop:disable Naming/InclusiveLanguage
page.driver.browser.url_blacklist = ['/rails/active_storage/'] # rubocop:disable Naming/InclusiveLanguage
page.driver.browser.url_blacklist = ['/rails/active_storage/representations'] # rubocop:disable Naming/InclusiveLanguage
end
after { page.driver.browser.url_blacklist = @original } # rubocop:disable Naming/InclusiveLanguage

Expand Down Expand Up @@ -45,4 +45,25 @@
expect(field_test.active_storage_assets.map { |image| image.filename.to_s }).to eq ['test.png']
end
end

describe 'direct upload', js: true do
let(:field_test) { FactoryBot.create :field_test }
before do
RailsAdmin.config FieldTest do
edit do
configure(:active_storage_assets) { direct true }
end
end
end

it 'works' do
visit edit_path(model_name: 'field_test', id: field_test.id)
attach_file 'Active storage assets', [file_path('test.jpg')]
expect_any_instance_of(ActiveStorage::DirectUploadsController).to receive(:create).and_call_original
click_button 'Save'
expect(page).to have_content 'Field test successfully updated'
field_test.reload
expect(field_test.active_storage_assets.map { |image| image.filename.to_s }).to eq ['test.jpg']
end
end
end
30 changes: 30 additions & 0 deletions spec/rails_admin/config/fields/types/active_storage_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,35 @@
expect(field.eager_load).to eq({active_storage_asset_attachment: :blob})
end
end

describe '#direct' do
let(:view) { double }
let(:field) do
RailsAdmin.config('FieldTest').fields.detect do |f|
f.name == :active_storage_asset
end.with(view: view)
end
before do
allow(view).to receive_message_chain(:main_app, :rails_direct_uploads_url) { 'http://www.example.com/rails/active_storage/direct_uploads' }
end

context 'when false' do
it "doesn't put the direct upload url in html_attributes" do
expect(field.html_attributes[:data]&.[](:direct_upload_url)).to be_nil
end
end

context 'when true' do
before do
RailsAdmin.config FieldTest do
field(:active_storage_asset) { direct true }
end
end

it 'puts the direct upload url in html_attributes' do
expect(field.html_attributes[:data]&.[](:direct_upload_url)).to eq 'http://www.example.com/rails/active_storage/direct_uploads'
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,35 @@
expect(field.eager_load).to eq({active_storage_assets_attachments: :blob})
end
end

describe '#direct' do
let(:view) { double }
let(:field) do
RailsAdmin.config('FieldTest').fields.detect do |f|
f.name == :active_storage_assets
end.with(view: view)
end
before do
allow(view).to receive_message_chain(:main_app, :rails_direct_uploads_url) { 'http://www.example.com/rails/active_storage/direct_uploads' }
end

context 'when false' do
it "doesn't put the direct upload url in html_attributes" do
expect(field.html_attributes[:data]&.[](:direct_upload_url)).to be_nil
end
end

context 'when true' do
before do
RailsAdmin.config FieldTest do
field(:active_storage_assets) { direct true }
end
end

it 'puts the direct upload url in html_attributes' do
expect(field.html_attributes[:data]&.[](:direct_upload_url)).to eq 'http://www.example.com/rails/active_storage/direct_uploads'
end
end
end
end
end
27 changes: 12 additions & 15 deletions src/rails_admin/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,18 @@ import I18n from "./i18n";
.each(function () {
$(this).siblings(".control-group").hide();
});
$('button[name][type="submit"]')
.attr("type", "button")
.on("click", function () {
var form = $(this).closest("form");
form.append(
$("<input />")
.attr("type", "hidden")
.attr("name", $(this).attr("name"))
.attr("value", $(this).attr("value"))
);
if ($(this).is("[formnovalidate]")) {
form.attr("novalidate", true);
}
form.trigger("submit");
});
$('button[name][type="submit"]').on("click", function () {
var form = $(this).closest("form");
form.append(
$("<input />")
.attr("type", "hidden")
.attr("name", $(this).attr("name"))
.attr("value", $(this).attr("value"))
);
if ($(this).is("[formnovalidate]")) {
form.attr("novalidate", true);
}
});
$.each($("#filters_box").data("options"), function () {
$.filters.append(this);
});
Expand Down

0 comments on commit 22b4973

Please sign in to comment.