activestorage_legacy 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. data/.babelrc +5 -0
  3. data/.codeclimate.yml +7 -0
  4. data/.eslintrc +19 -0
  5. data/.github/workflows/gem-push.yml +29 -0
  6. data/.github/workflows/ruby-tests.yml +37 -0
  7. data/.gitignore +9 -0
  8. data/.rubocop.yml +125 -0
  9. data/.travis.yml +25 -0
  10. data/Gemfile +33 -0
  11. data/Gemfile.lock +271 -0
  12. data/MIT-LICENSE +20 -0
  13. data/README.md +160 -0
  14. data/Rakefile +12 -0
  15. data/activestorage.gemspec +27 -0
  16. data/app/assets/javascripts/activestorage.js +1 -0
  17. data/app/controllers/active_storage/blobs_controller.rb +22 -0
  18. data/app/controllers/active_storage/direct_uploads_controller.rb +21 -0
  19. data/app/controllers/active_storage/disk_controller.rb +52 -0
  20. data/app/controllers/active_storage/variants_controller.rb +28 -0
  21. data/app/helpers/active_storage/file_field_with_direct_upload_helper.rb +18 -0
  22. data/app/javascript/activestorage/blob_record.js +54 -0
  23. data/app/javascript/activestorage/blob_upload.js +34 -0
  24. data/app/javascript/activestorage/direct_upload.js +42 -0
  25. data/app/javascript/activestorage/direct_upload_controller.js +67 -0
  26. data/app/javascript/activestorage/direct_uploads_controller.js +50 -0
  27. data/app/javascript/activestorage/file_checksum.js +53 -0
  28. data/app/javascript/activestorage/helpers.js +42 -0
  29. data/app/javascript/activestorage/index.js +11 -0
  30. data/app/javascript/activestorage/ujs.js +74 -0
  31. data/app/jobs/active_storage/purge_attachment_worker.rb +9 -0
  32. data/app/jobs/active_storage/purge_blob_worker.rb +9 -0
  33. data/app/models/active_storage/attachment.rb +33 -0
  34. data/app/models/active_storage/blob.rb +198 -0
  35. data/app/models/active_storage/filename.rb +49 -0
  36. data/app/models/active_storage/variant.rb +82 -0
  37. data/app/models/active_storage/variation.rb +53 -0
  38. data/config/routes.rb +9 -0
  39. data/config/storage_services.yml +34 -0
  40. data/lib/active_storage/attached/macros.rb +86 -0
  41. data/lib/active_storage/attached/many.rb +51 -0
  42. data/lib/active_storage/attached/one.rb +56 -0
  43. data/lib/active_storage/attached.rb +38 -0
  44. data/lib/active_storage/engine.rb +81 -0
  45. data/lib/active_storage/gem_version.rb +15 -0
  46. data/lib/active_storage/log_subscriber.rb +48 -0
  47. data/lib/active_storage/messages_metadata.rb +64 -0
  48. data/lib/active_storage/migration.rb +27 -0
  49. data/lib/active_storage/patches/active_record.rb +19 -0
  50. data/lib/active_storage/patches/delegation.rb +98 -0
  51. data/lib/active_storage/patches/secure_random.rb +26 -0
  52. data/lib/active_storage/patches.rb +4 -0
  53. data/lib/active_storage/service/azure_service.rb +115 -0
  54. data/lib/active_storage/service/configurator.rb +28 -0
  55. data/lib/active_storage/service/disk_service.rb +124 -0
  56. data/lib/active_storage/service/gcs_service.rb +79 -0
  57. data/lib/active_storage/service/mirror_service.rb +46 -0
  58. data/lib/active_storage/service/s3_service.rb +96 -0
  59. data/lib/active_storage/service.rb +113 -0
  60. data/lib/active_storage/verifier.rb +113 -0
  61. data/lib/active_storage/version.rb +8 -0
  62. data/lib/active_storage.rb +34 -0
  63. data/lib/tasks/activestorage.rake +20 -0
  64. data/package.json +33 -0
  65. data/test/controllers/direct_uploads_controller_test.rb +123 -0
  66. data/test/controllers/disk_controller_test.rb +57 -0
  67. data/test/controllers/variants_controller_test.rb +21 -0
  68. data/test/database/create_users_migration.rb +7 -0
  69. data/test/database/setup.rb +6 -0
  70. data/test/dummy/Rakefile +3 -0
  71. data/test/dummy/app/assets/config/manifest.js +5 -0
  72. data/test/dummy/app/assets/images/.keep +0 -0
  73. data/test/dummy/app/assets/javascripts/application.js +13 -0
  74. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  75. data/test/dummy/app/controllers/application_controller.rb +3 -0
  76. data/test/dummy/app/controllers/concerns/.keep +0 -0
  77. data/test/dummy/app/helpers/application_helper.rb +2 -0
  78. data/test/dummy/app/jobs/application_job.rb +2 -0
  79. data/test/dummy/app/models/application_record.rb +3 -0
  80. data/test/dummy/app/models/concerns/.keep +0 -0
  81. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  82. data/test/dummy/bin/bundle +3 -0
  83. data/test/dummy/bin/rails +4 -0
  84. data/test/dummy/bin/rake +4 -0
  85. data/test/dummy/bin/yarn +11 -0
  86. data/test/dummy/config/application.rb +22 -0
  87. data/test/dummy/config/boot.rb +5 -0
  88. data/test/dummy/config/database.yml +25 -0
  89. data/test/dummy/config/environment.rb +5 -0
  90. data/test/dummy/config/environments/development.rb +49 -0
  91. data/test/dummy/config/environments/production.rb +82 -0
  92. data/test/dummy/config/environments/test.rb +33 -0
  93. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  94. data/test/dummy/config/initializers/assets.rb +14 -0
  95. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  96. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  97. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  98. data/test/dummy/config/initializers/inflections.rb +16 -0
  99. data/test/dummy/config/initializers/mime_types.rb +4 -0
  100. data/test/dummy/config/initializers/secret_key.rb +3 -0
  101. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  102. data/test/dummy/config/routes.rb +2 -0
  103. data/test/dummy/config/secrets.yml +32 -0
  104. data/test/dummy/config/spring.rb +6 -0
  105. data/test/dummy/config/storage_services.yml +3 -0
  106. data/test/dummy/config.ru +5 -0
  107. data/test/dummy/db/.keep +0 -0
  108. data/test/dummy/lib/assets/.keep +0 -0
  109. data/test/dummy/log/.keep +0 -0
  110. data/test/dummy/package.json +5 -0
  111. data/test/dummy/public/404.html +67 -0
  112. data/test/dummy/public/422.html +67 -0
  113. data/test/dummy/public/500.html +66 -0
  114. data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
  115. data/test/dummy/public/apple-touch-icon.png +0 -0
  116. data/test/dummy/public/favicon.ico +0 -0
  117. data/test/filename_test.rb +36 -0
  118. data/test/fixtures/files/racecar.jpg +0 -0
  119. data/test/models/attachments_test.rb +122 -0
  120. data/test/models/blob_test.rb +47 -0
  121. data/test/models/variant_test.rb +27 -0
  122. data/test/service/.gitignore +1 -0
  123. data/test/service/azure_service_test.rb +14 -0
  124. data/test/service/configurations-example.yml +31 -0
  125. data/test/service/configurator_test.rb +14 -0
  126. data/test/service/disk_service_test.rb +12 -0
  127. data/test/service/gcs_service_test.rb +42 -0
  128. data/test/service/mirror_service_test.rb +62 -0
  129. data/test/service/s3_service_test.rb +52 -0
  130. data/test/service/shared_service_tests.rb +66 -0
  131. data/test/sidekiq/minitest_support.rb +6 -0
  132. data/test/support/assertions.rb +20 -0
  133. data/test/test_helper.rb +69 -0
  134. data/webpack.config.js +27 -0
  135. data/yarn.lock +3164 -0
  136. metadata +330 -0
@@ -0,0 +1,47 @@
1
+ require "test_helper"
2
+ require "database/setup"
3
+
4
+ class ActiveStorage::BlobTest < ActiveSupport::TestCase
5
+ test "create after upload sets byte size and checksum" do
6
+ data = "Hello world!"
7
+ blob = create_blob data: data
8
+
9
+ assert_equal data, blob.download
10
+ assert_equal data.length, blob.byte_size
11
+ assert_equal Digest::MD5.base64digest(data), blob.checksum
12
+ end
13
+
14
+ test "text?" do
15
+ blob = create_blob data: "Hello world!"
16
+ assert blob.text?
17
+ assert_not blob.audio?
18
+ end
19
+
20
+ test "download yields chunks" do
21
+ blob = create_blob data: "a" * 75.kilobytes
22
+ chunks = []
23
+
24
+ blob.download do |chunk|
25
+ chunks << chunk
26
+ end
27
+
28
+ assert_equal 2, chunks.size
29
+ assert_equal "a" * 64.kilobytes, chunks.first
30
+ assert_equal "a" * 11.kilobytes, chunks.second
31
+ end
32
+
33
+ test "urls expiring in 5 minutes" do
34
+ blob = create_blob
35
+
36
+ freeze_time do
37
+ assert_equal expected_url_for(blob), blob.service_url
38
+ assert_equal expected_url_for(blob, disposition: :attachment), blob.service_url(disposition: :attachment)
39
+ end
40
+ end
41
+
42
+ private
43
+ def expected_url_for(blob, disposition: :inline)
44
+ query_string = { content_type: blob.content_type, disposition: disposition }.to_param
45
+ "/rails/active_storage/disk/#{ActiveStorage.verifier.generate(blob.key, expires_in: 5.minutes, purpose: :blob_key)}/#{blob.filename}?#{query_string}"
46
+ end
47
+ end
@@ -0,0 +1,27 @@
1
+ require "test_helper"
2
+ require "database/setup"
3
+
4
+ class ActiveStorage::VariantTest < ActiveSupport::TestCase
5
+ setup do
6
+ @blob = create_image_blob filename: "racecar.jpg"
7
+ end
8
+
9
+ test "resized variation" do
10
+ variant = @blob.variant(resize: "100x100").processed
11
+ assert_match /racecar.jpg/, variant.service_url
12
+
13
+ image = read_image_variant(variant)
14
+ assert_equal 100, image.width
15
+ assert_equal 67, image.height
16
+ end
17
+
18
+ test "resized and monochrome variation" do
19
+ variant = @blob.variant(resize: "100x100", monochrome: true).processed
20
+ assert_match /racecar.jpg/, variant.service_url
21
+
22
+ image = read_image_variant(variant)
23
+ assert_equal 100, image.width
24
+ assert_equal 67, image.height
25
+ assert_match /Gray/, image.colorspace
26
+ end
27
+ end
@@ -0,0 +1 @@
1
+ configurations.yml
@@ -0,0 +1,14 @@
1
+ require "service/shared_service_tests"
2
+ require "httparty"
3
+ require "uri"
4
+
5
+ if SERVICE_CONFIGURATIONS[:azure]
6
+ class ActiveStorage::Service::AzureServiceTest < ActiveSupport::TestCase
7
+ SERVICE = ActiveStorage::Service.configure(:azure, SERVICE_CONFIGURATIONS)
8
+
9
+ include ActiveStorage::Service::SharedServiceTests
10
+ end
11
+
12
+ else
13
+ puts "Skipping Azure Storage Service tests because no Azure configuration was supplied"
14
+ end
@@ -0,0 +1,31 @@
1
+ # Copy this file to configurations.yml and edit the credentials to match your IAM test account and bucket
2
+ s3:
3
+ service: S3
4
+ access_key_id:
5
+ secret_access_key:
6
+ region:
7
+ bucket:
8
+
9
+ gcs:
10
+ service: GCS
11
+ keyfile: {
12
+ type: "service_account",
13
+ project_id: "",
14
+ private_key_id: "",
15
+ private_key: "",
16
+ client_email: "",
17
+ client_id: "",
18
+ auth_uri: "https://accounts.google.com/o/oauth2/auth",
19
+ token_uri: "https://accounts.google.com/o/oauth2/token",
20
+ auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
21
+ client_x509_cert_url: ""
22
+ }
23
+ project:
24
+ bucket:
25
+
26
+ azure:
27
+ service: Azure
28
+ path: ""
29
+ storage_account_name: ""
30
+ storage_access_key: ""
31
+ container: ""
@@ -0,0 +1,14 @@
1
+ require "service/shared_service_tests"
2
+
3
+ class ActiveStorage::Service::ConfiguratorTest < ActiveSupport::TestCase
4
+ test "builds correct service instance based on service name" do
5
+ service = ActiveStorage::Service::Configurator.build(:foo, foo: { service: "Disk", root: "path" })
6
+ assert_instance_of ActiveStorage::Service::DiskService, service
7
+ end
8
+
9
+ test "raises error when passing non-existent service name" do
10
+ assert_raise RuntimeError do
11
+ ActiveStorage::Service::Configurator.build(:bigfoot, {})
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ require "service/shared_service_tests"
2
+
3
+ class ActiveStorage::Service::DiskServiceTest < ActiveSupport::TestCase
4
+ SERVICE = ActiveStorage::Service::DiskService.new(root: File.join(Dir.tmpdir, "active_storage"))
5
+
6
+ include ActiveStorage::Service::SharedServiceTests
7
+
8
+ test "url generation" do
9
+ assert_match /rails\/active_storage\/disk\/.*\/avatar\.png\?.+disposition=inline/,
10
+ @service.url(FIXTURE_KEY, expires_in: 5.minutes, disposition: :inline, filename: "avatar.png", content_type: "image/png")
11
+ end
12
+ end
@@ -0,0 +1,42 @@
1
+ require "service/shared_service_tests"
2
+ require "httparty"
3
+
4
+ if SERVICE_CONFIGURATIONS[:gcs]
5
+ class ActiveStorage::Service::GCSServiceTest < ActiveSupport::TestCase
6
+ SERVICE = ActiveStorage::Service.configure(:gcs, SERVICE_CONFIGURATIONS)
7
+
8
+ include ActiveStorage::Service::SharedServiceTests
9
+
10
+ test "direct upload" do
11
+ begin
12
+ key = SecureRandom.base58(24)
13
+ data = "Something else entirely!"
14
+ checksum = Digest::MD5.base64digest(data)
15
+ url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum)
16
+
17
+ HTTParty.put(
18
+ url,
19
+ body: data,
20
+ headers: { "Content-Type" => "text/plain", "Content-MD5" => checksum },
21
+ debug_output: STDOUT
22
+ )
23
+
24
+ assert_equal data, @service.download(key)
25
+ ensure
26
+ @service.delete key
27
+ end
28
+ end
29
+
30
+ test "signed URL generation" do
31
+ freeze_time do
32
+ url = SERVICE.bucket.signed_url(FIXTURE_KEY, expires: 120) +
33
+ "&response-content-disposition=inline%3B+filename%3D%22test.txt%22" +
34
+ "&response-content-type=text%2Fplain"
35
+
36
+ assert_equal url, @service.url(FIXTURE_KEY, expires_in: 2.minutes, disposition: :inline, filename: "test.txt", content_type: "text/plain")
37
+ end
38
+ end
39
+ end
40
+ else
41
+ puts "Skipping GCS Service tests because no GCS configuration was supplied"
42
+ end
@@ -0,0 +1,62 @@
1
+ require "service/shared_service_tests"
2
+
3
+ class ActiveStorage::Service::MirrorServiceTest < ActiveSupport::TestCase
4
+ mirror_config = (1..3).map do |i|
5
+ [ "mirror_#{i}",
6
+ service: "Disk",
7
+ root: Dir.mktmpdir("active_storage_tests_mirror_#{i}") ]
8
+ end.to_h
9
+
10
+ config = mirror_config.merge \
11
+ mirror: { service: "Mirror", primary: "primary", mirrors: mirror_config.keys },
12
+ primary: { service: "Disk", root: Dir.mktmpdir("active_storage_tests_primary") }
13
+
14
+ SERVICE = ActiveStorage::Service.configure :mirror, config
15
+
16
+ include ActiveStorage::Service::SharedServiceTests
17
+
18
+ test "uploading to all services" do
19
+ begin
20
+ data = "Something else entirely!"
21
+ key = upload(data, to: @service)
22
+
23
+ assert_equal data, SERVICE.primary.download(key)
24
+ SERVICE.mirrors.each do |mirror|
25
+ assert_equal data, mirror.download(key)
26
+ end
27
+ ensure
28
+ @service.delete key
29
+ end
30
+ end
31
+
32
+ test "downloading from primary service" do
33
+ data = "Something else entirely!"
34
+ key = upload(data, to: SERVICE.primary)
35
+
36
+ assert_equal data, @service.download(key)
37
+ end
38
+
39
+ test "deleting from all services" do
40
+ @service.delete FIXTURE_KEY
41
+ assert_not SERVICE.primary.exist?(FIXTURE_KEY)
42
+ SERVICE.mirrors.each do |mirror|
43
+ assert_not mirror.exist?(FIXTURE_KEY)
44
+ end
45
+ end
46
+
47
+ test "URL generation in primary service" do
48
+ freeze_time do
49
+ assert_equal SERVICE.primary.url(FIXTURE_KEY, expires_in: 2.minutes, disposition: :inline, filename: "test.txt", content_type: "text/plain"),
50
+ @service.url(FIXTURE_KEY, expires_in: 2.minutes, disposition: :inline, filename: "test.txt", content_type: "text/plain")
51
+ end
52
+ end
53
+
54
+ private
55
+ def upload(data, to:)
56
+ SecureRandom.base58(24).tap do |key|
57
+ io = StringIO.new(data).tap(&:read)
58
+ @service.upload key, io, checksum: Digest::MD5.base64digest(data)
59
+ assert io.eof?
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,52 @@
1
+ require "service/shared_service_tests"
2
+ require "httparty"
3
+
4
+ if SERVICE_CONFIGURATIONS[:s3]
5
+ class ActiveStorage::Service::S3ServiceTest < ActiveSupport::TestCase
6
+ SERVICE = ActiveStorage::Service.configure(:s3, SERVICE_CONFIGURATIONS)
7
+
8
+ include ActiveStorage::Service::SharedServiceTests
9
+
10
+ test "direct upload" do
11
+ begin
12
+ key = SecureRandom.base58(24)
13
+ data = "Something else entirely!"
14
+ checksum = Digest::MD5.base64digest(data)
15
+ url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum)
16
+
17
+ HTTParty.put(
18
+ url,
19
+ body: data,
20
+ headers: { "Content-Type" => "text/plain", "Content-MD5" => checksum },
21
+ debug_output: STDOUT
22
+ )
23
+
24
+ assert_equal data, @service.download(key)
25
+ ensure
26
+ @service.delete key
27
+ end
28
+ end
29
+
30
+ test "signed URL generation" do
31
+ assert_match /#{SERVICE_CONFIGURATIONS[:s3][:bucket]}\.s3.(\S+)?amazonaws.com.*response-content-disposition=inline.*avatar\.png.*response-content-type=image%2Fpng/,
32
+ @service.url(FIXTURE_KEY, expires_in: 5.minutes, disposition: :inline, filename: "avatar.png", content_type: "image/png")
33
+ end
34
+
35
+ test "uploading with server-side encryption" do
36
+ config = SERVICE_CONFIGURATIONS.deep_merge(s3: { upload: { server_side_encryption: "AES256" }})
37
+ service = ActiveStorage::Service.configure(:s3, config)
38
+
39
+ begin
40
+ key = SecureRandom.base58(24)
41
+ data = "Something else entirely!"
42
+ service.upload key, StringIO.new(data), checksum: Digest::MD5.base64digest(data)
43
+
44
+ assert_equal "AES256", service.bucket.object(key).server_side_encryption
45
+ ensure
46
+ service.delete key
47
+ end
48
+ end
49
+ end
50
+ else
51
+ puts "Skipping S3 Service tests because no S3 configuration was supplied"
52
+ end
@@ -0,0 +1,66 @@
1
+ require "test_helper"
2
+
3
+ module ActiveStorage::Service::SharedServiceTests
4
+ extend ActiveSupport::Concern
5
+
6
+ FIXTURE_KEY = SecureRandom.base58(24)
7
+ FIXTURE_DATA = "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\000\020\000\000\000\020\001\003\000\000\000%=m\"\000\000\000\006PLTE\000\000\000\377\377\377\245\331\237\335\000\000\0003IDATx\234c\370\377\237\341\377_\206\377\237\031\016\2603\334?\314p\1772\303\315\315\f7\215\031\356\024\203\320\275\317\f\367\201R\314\f\017\300\350\377\177\000Q\206\027(\316]\233P\000\000\000\000IEND\256B`\202".force_encoding(Encoding::BINARY)
8
+
9
+ included do
10
+ setup do
11
+ @service = self.class.const_get(:SERVICE)
12
+ @service.upload FIXTURE_KEY, StringIO.new(FIXTURE_DATA)
13
+ end
14
+
15
+ teardown do
16
+ @service.delete FIXTURE_KEY
17
+ end
18
+
19
+ test "uploading with integrity" do
20
+ begin
21
+ key = SecureRandom.base58(24)
22
+ data = "Something else entirely!"
23
+ @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest(data))
24
+
25
+ assert_equal data, @service.download(key)
26
+ ensure
27
+ @service.delete key
28
+ end
29
+ end
30
+
31
+ test "uploading without integrity" do
32
+ begin
33
+ key = SecureRandom.base58(24)
34
+ data = "Something else entirely!"
35
+
36
+ assert_raises(ActiveStorage::IntegrityError) do
37
+ @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest("bad data"))
38
+ end
39
+
40
+ assert_not @service.exist?(key)
41
+ ensure
42
+ @service.delete key
43
+ end
44
+ end
45
+
46
+ test "downloading" do
47
+ assert_equal FIXTURE_DATA, @service.download(FIXTURE_KEY)
48
+ end
49
+
50
+ test "existing" do
51
+ assert @service.exist?(FIXTURE_KEY)
52
+ assert_not @service.exist?(FIXTURE_KEY + "nonsense")
53
+ end
54
+
55
+ test "deleting" do
56
+ @service.delete FIXTURE_KEY
57
+ assert_not @service.exist?(FIXTURE_KEY)
58
+ end
59
+
60
+ test "deleting nonexistent key" do
61
+ assert_nothing_raised do
62
+ @service.delete SecureRandom.base58(24)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,6 @@
1
+ module SidekiqMinitestSupport
2
+ def after_teardown
3
+ Sidekiq::Worker.clear_all
4
+ super
5
+ end
6
+ end
@@ -0,0 +1,20 @@
1
+ require 'minitest/mock'
2
+
3
+ module Assertions
4
+ def assert_not(object, message = nil)
5
+ message ||= "Expected #{object} to be nil or false"
6
+ assert !object, message
7
+ end
8
+
9
+ def freeze_time(&block)
10
+ if block
11
+ reference_date = Time.now
12
+
13
+ Time.stub :now, reference_date do
14
+ block.call
15
+ end
16
+ else
17
+ block.call
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,69 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter %r{^/test/}
4
+ end
5
+
6
+ require File.expand_path("../../test/dummy/config/environment.rb", __FILE__)
7
+
8
+ require "bundler/setup"
9
+
10
+ require "test/unit/active_support"
11
+
12
+ require "active_support"
13
+ require "active_support/test_case"
14
+
15
+ require "byebug"
16
+ require "sidekiq"
17
+ require 'sidekiq/testing'
18
+ require "sidekiq/minitest_support"
19
+
20
+ require "active_storage"
21
+
22
+ require "yaml"
23
+ SERVICE_CONFIGURATIONS = begin
24
+ YAML.load_file(File.expand_path("../service/configurations.yml", __FILE__)).deep_symbolize_keys
25
+ rescue Errno::ENOENT
26
+ puts "Missing service configuration file in test/service/configurations.yml"
27
+ {}
28
+ end
29
+
30
+ require "tmpdir"
31
+ require 'active_storage/service/disk_service'
32
+ require 'support/assertions'
33
+
34
+ ActiveStorage::Blob.service = ActiveStorage::Service::DiskService.new(root: Dir.mktmpdir("active_storage_tests"))
35
+ ActiveStorage::Service.logger = ::Logger.new(STDOUT)
36
+
37
+ ActiveStorage.verifier = ActiveStorage::Verifier.new('Testing')
38
+
39
+ class ActiveSupport::TestCase
40
+ include Assertions
41
+ include SidekiqMinitestSupport
42
+
43
+ private
44
+ def create_blob(data: "Hello world!", filename: "hello.txt", content_type: "text/plain")
45
+ ActiveStorage::Blob.create_after_upload! io: StringIO.new(data), filename: filename, content_type: content_type
46
+ end
47
+
48
+ def create_image_blob(filename: "racecar.jpg", content_type: "image/jpeg")
49
+ ActiveStorage::Blob.create_after_upload! \
50
+ io: file_fixture(filename).open,
51
+ filename: filename, content_type: content_type
52
+ end
53
+
54
+ def create_blob_before_direct_upload(filename: "hello.txt", byte_size:, checksum:, content_type: "text/plain")
55
+ ActiveStorage::Blob.create_before_direct_upload! filename: filename, byte_size: byte_size, checksum: checksum, content_type: content_type
56
+ end
57
+
58
+ def read_image_variant(variant)
59
+ MiniMagick::Image.open variant.service.send(:path_for, variant.key)
60
+ end
61
+
62
+ def file_fixture(filename)
63
+ Pathname(File.join(file_fixture_path, filename))
64
+ end
65
+
66
+ def file_fixture_path
67
+ File.expand_path("../fixtures/files", __FILE__)
68
+ end
69
+ end
data/webpack.config.js ADDED
@@ -0,0 +1,27 @@
1
+ const webpack = require("webpack")
2
+ const path = require("path")
3
+
4
+ module.exports = {
5
+ entry: {
6
+ "activestorage": path.resolve(__dirname, "app/javascript/activestorage/index.js"),
7
+ },
8
+
9
+ output: {
10
+ filename: "[name].js",
11
+ path: path.resolve(__dirname, "app/assets/javascripts"),
12
+ library: "ActiveStorage",
13
+ libraryTarget: "umd"
14
+ },
15
+
16
+ module: {
17
+ rules: [
18
+ {
19
+ test: /\.js$/,
20
+ exclude: /node_modules/,
21
+ use: {
22
+ loader: "babel-loader"
23
+ }
24
+ }
25
+ ]
26
+ }
27
+ }