diff options
Diffstat (limited to 'activestorage')
25 files changed, 123 insertions, 120 deletions
diff --git a/activestorage/README.md b/activestorage/README.md index 957adc05c3..d4ffe0c484 100644 --- a/activestorage/README.md +++ b/activestorage/README.md @@ -83,14 +83,6 @@ Variation of image attachment: <%= image_tag user.avatar.variant(resize: "100x100") %> ``` -## Installation - -1. Run `rails activestorage:install` to create needed directories, migrations, and configuration. -2. Optional: Add `gem "aws-sdk", "~> 2"` to your Gemfile if you want to use AWS S3. -3. Optional: Add `gem "google-cloud-storage", "~> 1.3"` to your Gemfile if you want to use Google Cloud Storage. -4. Optional: Add `gem "azure-storage"` to your Gemfile if you want to use Microsoft Azure. -5. Optional: Add `gem "mini_magick"` to your Gemfile if you want to use variants. - ## Direct uploads Active Storage, with its included JavaScript library, supports uploading directly from the client to the cloud. diff --git a/activestorage/app/controllers/active_storage/blobs_controller.rb b/activestorage/app/controllers/active_storage/blobs_controller.rb index 05af29f8b2..cff88bd488 100644 --- a/activestorage/app/controllers/active_storage/blobs_controller.rb +++ b/activestorage/app/controllers/active_storage/blobs_controller.rb @@ -5,6 +5,7 @@ class ActiveStorage::BlobsController < ActionController::Base def show if blob = find_signed_blob + expires_in 5.minutes # service_url defaults to 5 minutes redirect_to blob.service_url(disposition: disposition_param) else head :not_found diff --git a/activestorage/app/controllers/active_storage/variants_controller.rb b/activestorage/app/controllers/active_storage/variants_controller.rb index 994c57aafd..b72b0ff7f5 100644 --- a/activestorage/app/controllers/active_storage/variants_controller.rb +++ b/activestorage/app/controllers/active_storage/variants_controller.rb @@ -5,6 +5,7 @@ class ActiveStorage::VariantsController < ActionController::Base def show if blob = find_signed_blob + expires_in 5.minutes # service_url defaults to 5 minutes redirect_to ActiveStorage::Variant.new(blob, decoded_variation).processed.service_url(disposition: disposition_param) else head :not_found diff --git a/activestorage/app/jobs/active_storage/purge_job.rb b/activestorage/app/jobs/active_storage/purge_job.rb index 815f908e6c..b504ee0df4 100644 --- a/activestorage/app/jobs/active_storage/purge_job.rb +++ b/activestorage/app/jobs/active_storage/purge_job.rb @@ -1,4 +1,4 @@ -# Provides delayed purging of attachments or blobs using their `#purge_later` method. +# Provides delayed purging of attachments or blobs using their +#purge_later+ method. class ActiveStorage::PurgeJob < ActiveJob::Base # FIXME: Limit this to a custom ActiveStorage error retry_on StandardError diff --git a/activestorage/app/models/active_storage/attachment.rb b/activestorage/app/models/active_storage/attachment.rb index e94fc69bba..07b5733ff8 100644 --- a/activestorage/app/models/active_storage/attachment.rb +++ b/activestorage/app/models/active_storage/attachment.rb @@ -21,7 +21,7 @@ class ActiveStorage::Attachment < ActiveRecord::Base # Purging an attachment means purging the blob, which means talking to the service, which means # talking over the internet. Whenever you're doing that, it's a good idea to put that work in a job, - # so it doesn't hold up other operations. That's what #purge_later provides. + # so it doesn't hold up other operations. That's what +#purge_later+ provides. def purge_later ActiveStorage::PurgeJob.perform_later(self) end diff --git a/activestorage/app/models/active_storage/blob.rb b/activestorage/app/models/active_storage/blob.rb index c72073f9f6..113a7f774d 100644 --- a/activestorage/app/models/active_storage/blob.rb +++ b/activestorage/app/models/active_storage/blob.rb @@ -29,7 +29,7 @@ class ActiveStorage::Blob < ActiveRecord::Base find ActiveStorage.verifier.verify(id, purpose: :blob_id) end - # Returns a new, unsaved blob instance after the `io` has been uploaded to the service. + # Returns a new, unsaved blob instance after the +io+ has been uploaded to the service. def build_after_upload(io:, filename:, content_type: nil, metadata: nil) new.tap do |blob| blob.filename = filename @@ -40,8 +40,8 @@ class ActiveStorage::Blob < ActiveRecord::Base end end - # Returns a saved blob instance after the `io` has been uploaded to the service. Note, the blob is first built, - # then the `io` is uploaded, then the blob is saved. This is doing to avoid opening a transaction and talking to + # Returns a saved blob instance after the +io+ has been uploaded to the service. Note, the blob is first built, + # then the +io+ is uploaded, then the blob is saved. This is doing to avoid opening a transaction and talking to # the service during that (which is a bad idea and leads to deadlocks). def create_after_upload!(io:, filename:, content_type: nil, metadata: nil) build_after_upload(io: io, filename: filename, content_type: content_type, metadata: metadata).tap(&:save!) @@ -72,7 +72,7 @@ class ActiveStorage::Blob < ActiveRecord::Base self[:key] ||= self.class.generate_unique_secure_token end - # Returns a `ActiveStorage::Filename` instance of the filename that can be queried for basename, extension, and + # Returns a ActiveStorage::Filename instance of the filename that can be queried for basename, extension, and # a sanitized version of the filename that's safe to use in URLs. def filename ActiveStorage::Filename.new(self[:filename]) @@ -98,7 +98,7 @@ class ActiveStorage::Blob < ActiveRecord::Base content_type.start_with?("text") end - # Returns a `ActiveStorage::Variant` instance with the set of `transformations` passed in. This is only relevant + # Returns a ActiveStorage::Variant instance with the set of +transformations+ passed in. This is only relevant # for image files, and it allows any image to be transformed for size, colors, and the like. Example: # # avatar.variant(resize: "100x100").processed.service_url @@ -111,7 +111,7 @@ class ActiveStorage::Blob < ActiveRecord::Base # # <%= image_tag url_for(Current.user.avatar.variant(resize: "100x100")) %> # - # This will create a URL for that specific blob with that specific variant, which the `ActiveStorage::VariantsController` + # This will create a URL for that specific blob with that specific variant, which the ActiveStorage::VariantsController # can then produce on-demand. def variant(transformations) ActiveStorage::Variant.new(self, ActiveStorage::Variation.new(transformations)) @@ -119,9 +119,9 @@ class ActiveStorage::Blob < ActiveRecord::Base # Returns the URL of the blob on the service. This URL is intended to be short-lived for security and not used directly - # with users. Instead, the `service_url` should only be exposed as a redirect from a stable, possibly authenticated URL. - # Hiding the `service_url` behind a redirect also gives you the power to change services without updating all URLs. And - # it allows permanent URLs that redirect to the `service_url` to be cached in the view. + # with users. Instead, the +service_url+ should only be exposed as a redirect from a stable, possibly authenticated URL. + # Hiding the +service_url+ behind a redirect also gives you the power to change services without updating all URLs. And + # it allows permanent URLs that redirect to the +service_url+ to be cached in the view. def service_url(expires_in: 5.minutes, disposition: :inline) service.url key, expires_in: expires_in, disposition: disposition, filename: filename, content_type: content_type end @@ -132,21 +132,21 @@ class ActiveStorage::Blob < ActiveRecord::Base service.url_for_direct_upload key, expires_in: expires_in, content_type: content_type, content_length: byte_size, checksum: checksum end - # Returns a Hash of headers for `service_url_for_direct_upload` requests. + # Returns a Hash of headers for +service_url_for_direct_upload+ requests. def service_headers_for_direct_upload service.headers_for_direct_upload key, filename: filename, content_type: content_type, content_length: byte_size, checksum: checksum end - # Uploads the `io` to the service on the `key` for this blob. Blobs are intended to be immutable, so you shouldn't be + # Uploads the +io+ to the service on the +key+ for this blob. Blobs are intended to be immutable, so you shouldn't be # using this method after a file has already been uploaded to fit with a blob. If you want to create a derivative blob, # you should instead simply create a new blob based on the old one. # # Prior to uploading, we compute the checksum, which is sent to the service for transit integrity validation. If the - # checksum does not match what the service receives, an exception will be raised. We also measure the size of the `io` - # and store that in `byte_size` on the blob record. + # checksum does not match what the service receives, an exception will be raised. We also measure the size of the +io+ + # and store that in +byte_size+ on the blob record. # - # Normally, you do not have to call this method directly at all. Use the factory class methods of `build_after_upload` - # and `create_after_upload!`. + # Normally, you do not have to call this method directly at all. Use the factory class methods of +build_after_upload+ + # and +create_after_upload!+. def upload(io) self.checksum = compute_checksum_in_chunks(io) self.byte_size = io.size @@ -162,7 +162,7 @@ class ActiveStorage::Blob < ActiveRecord::Base # Deletes the file on the service that's associated with this blob. This should only be done if the blob is going to be - # deleted as well or you will essentially have a dead reference. It's recommended to use the `#purge` and `#purge_later` + # deleted as well or you will essentially have a dead reference. It's recommended to use the +#purge+ and +#purge_later+ # methods in most circumstances. def delete service.delete key @@ -170,13 +170,13 @@ class ActiveStorage::Blob < ActiveRecord::Base # Deletes the file on the service and then destroys the blob record. This is the recommended way to dispose of unwanted # blobs. Note, though, that deleting the file off the service will initiate a HTTP connection to the service, which may - # be slow or prevented, so you should not use this method inside a transaction or in callbacks. Use `#purge_later` instead. + # be slow or prevented, so you should not use this method inside a transaction or in callbacks. Use +#purge_later+ instead. def purge delete destroy end - # Enqueues a `ActiveStorage::PurgeJob` job that'll call `#purge`. This is the recommended way to purge blobs when the call + # Enqueues a ActiveStorage::PurgeJob job that'll call +#purge+. This is the recommended way to purge blobs when the call # needs to be made from a transaction, a callback, or any other real-time scenario. def purge_later ActiveStorage::PurgeJob.perform_later(self) diff --git a/activestorage/app/models/active_storage/variant.rb b/activestorage/app/models/active_storage/variant.rb index e3f22bcb25..b9b93b4c1b 100644 --- a/activestorage/app/models/active_storage/variant.rb +++ b/activestorage/app/models/active_storage/variant.rb @@ -9,17 +9,17 @@ # into memory. The larger the image, the more memory is used. Because of this process, you also want to be # considerate about when the variant is actually processed. You shouldn't be processing variants inline in a # template, for example. Delay the processing to an on-demand controller, like the one provided in -# `ActiveStorage::VariantsController`. +# ActiveStorage::VariantsController. # # To refer to such a delayed on-demand variant, simply link to the variant through the resolved route provided # by Active Storage like so: # # <%= image_tag url_for(Current.user.avatar.variant(resize: "100x100")) %> # -# This will create a URL for that specific blob with that specific variant, which the `ActiveStorage::VariantsController` +# This will create a URL for that specific blob with that specific variant, which the ActiveStorage::VariantsController # can then produce on-demand. # -# When you do want to actually produce the variant needed, call `#processed`. This will check that the variant +# When you do want to actually produce the variant needed, call +#processed+. This will check that the variant # has already been processed and uploaded to the service, and, if so, just return that. Otherwise it will perform # the transformations, upload the variant to the service, and return itself again. Example: # @@ -52,12 +52,12 @@ class ActiveStorage::Variant end # Returns the URL of the variant on the service. This URL is intended to be short-lived for security and not used directly - # with users. Instead, the `service_url` should only be exposed as a redirect from a stable, possibly authenticated URL. - # Hiding the `service_url` behind a redirect also gives you the power to change services without updating all URLs. And - # it allows permanent URLs that redirec to the `service_url` to be cached in the view. + # with users. Instead, the +service_url+ should only be exposed as a redirect from a stable, possibly authenticated URL. + # Hiding the +service_url+ behind a redirect also gives you the power to change services without updating all URLs. And + # it allows permanent URLs that redirect to the +service_url+ to be cached in the view. # # Use `url_for(variant)` (or the implied form, like `link_to variant` or `redirect_to variant`) to get the stable URL - # for a variant that points to the `ActiveStorage::VariantsController`, which in turn will use this `#service_call` method + # for a variant that points to the ActiveStorage::VariantsController, which in turn will use this +#service_call+ method # for its redirection. def service_url(expires_in: 5.minutes, disposition: :inline) service.url key, expires_in: expires_in, disposition: disposition, filename: blob.filename, content_type: blob.content_type diff --git a/activestorage/app/models/active_storage/variation.rb b/activestorage/app/models/active_storage/variation.rb index e784506b4c..24168c064c 100644 --- a/activestorage/app/models/active_storage/variation.rb +++ b/activestorage/app/models/active_storage/variation.rb @@ -13,12 +13,12 @@ class ActiveStorage::Variation attr_reader :transformations class << self - # Returns a variation instance with the transformations that were encoded by `#encode`. + # Returns a variation instance with the transformations that were encoded by +#encode+. def decode(key) new ActiveStorage.verifier.verify(key, purpose: :variation) end - # Returns a signed key for the `transformations`, which can be used to refer to a specific + # Returns a signed key for the +transformations+, which can be used to refer to a specific # variation in a URL or combined key (like `ActiveStorage::Variant#key`). def encode(transformations) ActiveStorage.verifier.generate(transformations, purpose: :variation) @@ -30,7 +30,7 @@ class ActiveStorage::Variation end # Accepts an open MiniMagick image instance, like what's return by `MiniMagick::Image.read(io)`, - # and performs the `transformations` against it. The transformed image instance is then returned. + # and performs the +transformations+ against it. The transformed image instance is then returned. def transform(image) transformations.each do |(method, argument)| if eligible_argument?(argument) @@ -41,7 +41,7 @@ class ActiveStorage::Variation end end - # Returns a signed key for all the `transformations` that this variation was instantiated with. + # Returns a signed key for all the +transformations+ that this variation was instantiated with. def key self.class.encode(transformations) end diff --git a/activestorage/db/migrate/20170806125915_create_active_storage_tables.rb b/activestorage/db/migrate/20170806125915_create_active_storage_tables.rb index 6eab7e0fa0..2c7e3c5bc6 100644 --- a/activestorage/db/migrate/20170806125915_create_active_storage_tables.rb +++ b/activestorage/db/migrate/20170806125915_create_active_storage_tables.rb @@ -1,24 +1,24 @@ class CreateActiveStorageTables < ActiveRecord::Migration[5.1] def change create_table :active_storage_blobs do |t| - t.string :key - t.string :filename + t.string :key, null: false + t.string :filename, null: false t.string :content_type t.text :metadata - t.integer :byte_size - t.string :checksum - t.datetime :created_at + t.integer :byte_size, null: false + t.string :checksum, null: false + t.datetime :created_at, null: false t.index [ :key ], unique: true end create_table :active_storage_attachments do |t| - t.string :name - t.string :record_type - t.integer :record_id - t.integer :blob_id + t.string :name, null: false + t.string :record_type, null: false + t.integer :record_id, null: false + t.integer :blob_id, null: false - t.datetime :created_at + t.datetime :created_at, null: false t.index :blob_id t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true diff --git a/activestorage/lib/active_storage/attached.rb b/activestorage/lib/active_storage/attached.rb index 5ac8ba5377..07e0d5c3ea 100644 --- a/activestorage/lib/active_storage/attached.rb +++ b/activestorage/lib/active_storage/attached.rb @@ -3,7 +3,7 @@ require "action_dispatch/http/upload" require "active_support/core_ext/module/delegation" module ActiveStorage -# Abstract baseclass for the concrete `ActiveStorage::Attached::One` and `ActiveStorage::Attached::Many` +# Abstract baseclass for the concrete ActiveStorage::Attached::One and ActiveStorage::Attached::Many # classes that both provide proxy access to the blob association for a record. class Attached attr_reader :name, :record diff --git a/activestorage/lib/active_storage/attached/macros.rb b/activestorage/lib/active_storage/attached/macros.rb index ef00033aeb..eb877f10c0 100644 --- a/activestorage/lib/active_storage/attached/macros.rb +++ b/activestorage/lib/active_storage/attached/macros.rb @@ -10,25 +10,23 @@ module ActiveStorage # There is no column defined on the model side, Active Storage takes # care of the mapping between your records and the attachment. # - # Under the covers, this relationship is implemented as a `has_one` association to a - # `ActiveStorage::Attachment` record and a `has_one-through` association to a - # `ActiveStorage::Blob` record. These associations are available as `avatar_attachment` - # and `avatar_blob`. But you shouldn't need to work with these associations directly in + # Under the covers, this relationship is implemented as a +has_one+ association to a + # ActiveStorage::Attachment record and a +has_one-through+ association to a + # ActiveStorage::Blob record. These associations are available as +avatar_attachment+ + # and +avatar_blob+. But you shouldn't need to work with these associations directly in # most circumstances. # - # The system has been designed to having you go through the `ActiveStorage::Attached::One` - # proxy that provides the dynamic proxy to the associations and factory methods, like `#attach`. + # The system has been designed to having you go through the ActiveStorage::Attached::One + # proxy that provides the dynamic proxy to the associations and factory methods, like +#attach+. # # If the +:dependent+ option isn't set, the attachment will be purged # (i.e. destroyed) whenever the record is destroyed. def has_one_attached(name, dependent: :purge_later) - define_method(name) do - if instance_variable_defined?("@active_storage_attached_#{name}") - instance_variable_get("@active_storage_attached_#{name}") - else - instance_variable_set("@active_storage_attached_#{name}", ActiveStorage::Attached::One.new(name, self)) + class_eval <<-CODE, __FILE__, __LINE__ + 1 + def #{name} + @active_storage_attached_#{name} ||= ActiveStorage::Attached::One.new("#{name}", self) end - end + CODE has_one :"#{name}_attachment", -> { where(name: name) }, class_name: "ActiveStorage::Attachment", as: :record has_one :"#{name}_blob", through: :"#{name}_attachment", class_name: "ActiveStorage::Blob", source: :blob @@ -51,25 +49,23 @@ module ActiveStorage # # Gallery.where(user: Current.user).with_attached_photos # - # Under the covers, this relationship is implemented as a `has_many` association to a - # `ActiveStorage::Attachment` record and a `has_many-through` association to a - # `ActiveStorage::Blob` record. These associations are available as `photos_attachments` - # and `photos_blobs`. But you shouldn't need to work with these associations directly in + # Under the covers, this relationship is implemented as a +has_many+ association to a + # ActiveStorage::Attachment record and a +has_many-through+ association to a + # ActiveStorage::Blob record. These associations are available as +photos_attachments+ + # and +photos_blobs+. But you shouldn't need to work with these associations directly in # most circumstances. # - # The system has been designed to having you go through the `ActiveStorage::Attached::Many` - # proxy that provides the dynamic proxy to the associations and factory methods, like `#attach`. + # The system has been designed to having you go through the ActiveStorage::Attached::Many + # proxy that provides the dynamic proxy to the associations and factory methods, like +#attach+. # # If the +:dependent+ option isn't set, all the attachments will be purged # (i.e. destroyed) whenever the record is destroyed. def has_many_attached(name, dependent: :purge_later) - define_method(name) do - if instance_variable_defined?("@active_storage_attached_#{name}") - instance_variable_get("@active_storage_attached_#{name}") - else - instance_variable_set("@active_storage_attached_#{name}", ActiveStorage::Attached::Many.new(name, self)) + class_eval <<-CODE, __FILE__, __LINE__ + 1 + def #{name} + @active_storage_attached_#{name} ||= ActiveStorage::Attached::Many.new("#{name}", self) end - end + CODE has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "ActiveStorage::Attachment" has_many :"#{name}_blobs", through: :"#{name}_attachments", class_name: "ActiveStorage::Blob", source: :blob diff --git a/activestorage/lib/active_storage/attached/many.rb b/activestorage/lib/active_storage/attached/many.rb index 1723756831..cc3e70ffe2 100644 --- a/activestorage/lib/active_storage/attached/many.rb +++ b/activestorage/lib/active_storage/attached/many.rb @@ -5,7 +5,7 @@ module ActiveStorage # Returns all the associated attachment records. # - # All methods called on this proxy object that aren't listed here will automatically be delegated to `attachments`. + # All methods called on this proxy object that aren't listed here will automatically be delegated to +attachments+. def attachments record.public_send("#{name}_attachments") end diff --git a/activestorage/lib/active_storage/engine.rb b/activestorage/lib/active_storage/engine.rb index d5bc70fc0c..a5562b32d3 100644 --- a/activestorage/lib/active_storage/engine.rb +++ b/activestorage/lib/active_storage/engine.rb @@ -5,6 +5,8 @@ require "active_storage" module ActiveStorage class Engine < Rails::Engine # :nodoc: + isolate_namespace ActiveStorage + config.active_storage = ActiveSupport::OrderedOptions.new config.eager_load_namespaces << ActiveStorage diff --git a/activestorage/lib/active_storage/service.rb b/activestorage/lib/active_storage/service.rb index eb25e9f001..4dd6eb6045 100644 --- a/activestorage/lib/active_storage/service.rb +++ b/activestorage/lib/active_storage/service.rb @@ -59,43 +59,43 @@ module ActiveStorage end end - # Upload the `io` to the `key` specified. If a `checksum` is provided, the service will - # ensure a match when the upload has completed or raise an `ActiveStorage::IntegrityError`. + # Upload the +io+ to the +key+ specified. If a +checksum+ is provided, the service will + # ensure a match when the upload has completed or raise an ActiveStorage::IntegrityError. def upload(key, io, checksum: nil) raise NotImplementedError end - # Return the content of the file at the `key`. + # Return the content of the file at the +key+. def download(key) raise NotImplementedError end - # Delete the file at the `key`. + # Delete the file at the +key+. def delete(key) raise NotImplementedError end - # Return true if a file exists at the `key`. + # Return true if a file exists at the +key+. def exist?(key) raise NotImplementedError end - # Returns a signed, temporary URL for the file at the `key`. The URL will be valid for the amount - # of seconds specified in `expires_in`. You most also provide the `disposition` (`:inline` or `:attachment`), - # `filename`, and `content_type` that you wish the file to be served with on request. + # Returns a signed, temporary URL for the file at the +key+. The URL will be valid for the amount + # of seconds specified in +expires_in+. You most also provide the +disposition+ (+:inline+ or +:attachment+), + # +filename+, and +content_type+ that you wish the file to be served with on request. def url(key, expires_in:, disposition:, filename:, content_type:) raise NotImplementedError end - # Returns a signed, temporary URL that a direct upload file can be PUT to on the `key`. - # The URL will be valid for the amount of seconds specified in `expires_in`. - # You most also provide the `content_type`, `content_length`, and `checksum` of the file + # Returns a signed, temporary URL that a direct upload file can be PUT to on the +key+. + # The URL will be valid for the amount of seconds specified in +expires_in+. + # You most also provide the +content_type+, +content_length+, and +checksum+ of the file # that will be uploaded. All these attributes will be validated by the service upon upload. def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:) raise NotImplementedError end - # Returns a Hash of headers for `url_for_direct_upload` requests. + # Returns a Hash of headers for +url_for_direct_upload+ requests. def headers_for_direct_upload(key, filename:, content_type:, content_length:, checksum:) {} end diff --git a/activestorage/lib/active_storage/service/azure_storage_service.rb b/activestorage/lib/active_storage/service/azure_storage_service.rb index 2e0b20cce3..d1c62f7db1 100644 --- a/activestorage/lib/active_storage/service/azure_storage_service.rb +++ b/activestorage/lib/active_storage/service/azure_storage_service.rb @@ -4,7 +4,7 @@ require "azure/storage/core/auth/shared_access_signature" module ActiveStorage # Wraps the Microsoft Azure Storage Blob Service as a Active Storage service. - # See `ActiveStorage::Service` for the generic API documentation that applies to all services. + # See ActiveStorage::Service for the generic API documentation that applies to all services. class Service::AzureStorageService < Service attr_reader :client, :path, :blobs, :container, :signer diff --git a/activestorage/lib/active_storage/service/disk_service.rb b/activestorage/lib/active_storage/service/disk_service.rb index cae7908126..9498761cc5 100644 --- a/activestorage/lib/active_storage/service/disk_service.rb +++ b/activestorage/lib/active_storage/service/disk_service.rb @@ -4,7 +4,7 @@ require "digest/md5" require "active_support/core_ext/numeric/bytes" module ActiveStorage - # Wraps a local disk path as a Active Storage service. See `ActiveStorage::Service` for the generic API + # Wraps a local disk path as a Active Storage service. See ActiveStorage::Service for the generic API # documentation that applies to all services. class Service::DiskService < Service attr_reader :root diff --git a/activestorage/lib/active_storage/service/gcs_service.rb b/activestorage/lib/active_storage/service/gcs_service.rb index ea4ec5a790..0707f26a74 100644 --- a/activestorage/lib/active_storage/service/gcs_service.rb +++ b/activestorage/lib/active_storage/service/gcs_service.rb @@ -2,7 +2,7 @@ require "google/cloud/storage" require "active_support/core_ext/object/to_query" module ActiveStorage - # Wraps the Google Cloud Storage as a Active Storage service. See `ActiveStorage::Service` for the generic API + # Wraps the Google Cloud Storage as a Active Storage service. See ActiveStorage::Service for the generic API # documentation that applies to all services. class Service::GCSService < Service attr_reader :client, :bucket diff --git a/activestorage/lib/active_storage/service/mirror_service.rb b/activestorage/lib/active_storage/service/mirror_service.rb index 2403eeb1e9..8491df4911 100644 --- a/activestorage/lib/active_storage/service/mirror_service.rb +++ b/activestorage/lib/active_storage/service/mirror_service.rb @@ -1,9 +1,9 @@ require "active_support/core_ext/module/delegation" module ActiveStorage - # Wraps a set of mirror services and provides a single `ActiveStorage::Service` object that will all - # have the files uploaded to them. A `primary` service is designated to answer calls to `download`, `exists?`, - # and `url`. + # Wraps a set of mirror services and provides a single ActiveStorage::Service object that will all + # have the files uploaded to them. A +primary+ service is designated to answer calls to +download+, +exists?+, + # and +url+. class Service::MirrorService < Service attr_reader :primary, :mirrors @@ -20,15 +20,15 @@ module ActiveStorage @primary, @mirrors = primary, mirrors end - # Upload the `io` to the `key` specified to all services. If a `checksum` is provided, all services will - # ensure a match when the upload has completed or raise an `ActiveStorage::IntegrityError`. + # Upload the +io+ to the +key+ specified to all services. If a +checksum+ is provided, all services will + # ensure a match when the upload has completed or raise an ActiveStorage::IntegrityError. def upload(key, io, checksum: nil) each_service.collect do |service| service.upload key, io.tap(&:rewind), checksum: checksum end end - # Delete the file at the `key` on all services. + # Delete the file at the +key+ on all services. def delete(key) perform_across_services :delete, key end diff --git a/activestorage/lib/active_storage/service/s3_service.rb b/activestorage/lib/active_storage/service/s3_service.rb index 5153f5db0d..b25eb409ef 100644 --- a/activestorage/lib/active_storage/service/s3_service.rb +++ b/activestorage/lib/active_storage/service/s3_service.rb @@ -3,7 +3,7 @@ require "active_support/core_ext/numeric/bytes" module ActiveStorage # Wraps the Amazon Simple Storage Service (S3) as a Active Storage service. - # See `ActiveStorage::Service` for the generic API documentation that applies to all services. + # See ActiveStorage::Service for the generic API documentation that applies to all services. class Service::S3Service < Service attr_reader :client, :bucket, :upload_options diff --git a/activestorage/lib/tasks/activestorage.rake b/activestorage/lib/tasks/activestorage.rake index d9e240b141..7a573be596 100644 --- a/activestorage/lib/tasks/activestorage.rake +++ b/activestorage/lib/tasks/activestorage.rake @@ -1,6 +1,6 @@ namespace :activestorage do desc "Copy over the migration needed to the application" task install: :environment do - Rake::Task["active_storage_engine:install:migrations"].invoke + Rake::Task["active_storage:install:migrations"].invoke end end diff --git a/activestorage/test/controllers/blobs_controller_test.rb b/activestorage/test/controllers/blobs_controller_test.rb new file mode 100644 index 0000000000..5ec353889c --- /dev/null +++ b/activestorage/test/controllers/blobs_controller_test.rb @@ -0,0 +1,15 @@ +require "test_helper" +require "database/setup" + +class ActiveStorage::BlobsControllerTest < ActionDispatch::IntegrationTest + setup do + @blob = create_image_blob filename: "racecar.jpg" + end + + test "showing blob utilizes browser caching" do + get rails_blob_url(@blob) + + assert_redirected_to(/racecar.jpg/) + assert_equal "max-age=300, private", @response.headers["Cache-Control"] + end +end diff --git a/activestorage/test/models/attachments_test.rb b/activestorage/test/models/attachments_test.rb index 82256e1f44..58af5dce6e 100644 --- a/activestorage/test/models/attachments_test.rb +++ b/activestorage/test/models/attachments_test.rb @@ -1,13 +1,6 @@ require "test_helper" require "database/setup" -# ActiveRecord::Base.logger = Logger.new(STDOUT) - -class User < ActiveRecord::Base - has_one_attached :avatar - has_many_attached :highlights -end - class ActiveStorage::AttachmentsTest < ActiveSupport::TestCase include ActiveJob::TestHelper diff --git a/activestorage/test/service/configurations.yml b/activestorage/test/service/configurations.yml index d7aa672573..56ed37be5d 100644 --- a/activestorage/test/service/configurations.yml +++ b/activestorage/test/service/configurations.yml @@ -1,10 +1,10 @@ -s3: - service: S3 - access_key_id: <%= ENV["AWS_ACCESS_KEY_ID"] %> - secret_access_key: <%= ENV["AWS_SECRET_KEY"] %> - region: us-east-2 - bucket: rails-ci-activestorage - +# s3: +# service: S3 +# access_key_id: "" +# secret_access_key: "" +# region: "" +# bucket: "" +# # gcs: # service: GCS # keyfile: { diff --git a/activestorage/test/template/image_tag_test.rb b/activestorage/test/template/image_tag_test.rb index 83c95c01a1..b285cd2e14 100644 --- a/activestorage/test/template/image_tag_test.rb +++ b/activestorage/test/template/image_tag_test.rb @@ -1,10 +1,6 @@ require "test_helper" require "database/setup" -class User < ActiveRecord::Base - has_one_attached :avatar -end - class ActiveStorage::ImageTagTest < ActionView::TestCase tests ActionView::Helpers::AssetTagHelper diff --git a/activestorage/test/test_helper.rb b/activestorage/test/test_helper.rb index 50cc72cbe3..1190daa7b0 100644 --- a/activestorage/test/test_helper.rb +++ b/activestorage/test/test_helper.rb @@ -4,13 +4,15 @@ require "bundler/setup" require "active_support" require "active_support/test_case" require "active_support/testing/autorun" -require "byebug" + +begin + require "byebug" +rescue LoadError +end require "active_job" ActiveJob::Base.queue_adapter = :test -ActiveJob::Base.logger = nil - -require "active_storage" +ActiveJob::Base.logger = ActiveSupport::Logger.new(nil) # Filter out Minitest backtrace while allowing backtrace from other libraries # to be shown. @@ -58,3 +60,8 @@ end require "global_id" GlobalID.app = "ActiveStorageExampleApp" ActiveRecord::Base.send :include, GlobalID::Identification + +class User < ActiveRecord::Base + has_one_attached :avatar + has_many_attached :highlights +end |