diff options
Diffstat (limited to 'activestorage/lib')
18 files changed, 98 insertions, 104 deletions
diff --git a/activestorage/lib/active_storage.rb b/activestorage/lib/active_storage.rb index 412f08e8f5..ccc1d4a163 100644 --- a/activestorage/lib/active_storage.rb +++ b/activestorage/lib/active_storage.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + #-- # Copyright (c) 2017 David Heinemeier Hansson # diff --git a/activestorage/lib/active_storage/attached.rb b/activestorage/lib/active_storage/attached.rb index 5ac8ba5377..e90b75afd0 100644 --- a/activestorage/lib/active_storage/attached.rb +++ b/activestorage/lib/active_storage/attached.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + require "action_dispatch" 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 @@ -17,7 +19,7 @@ module ActiveStorage case attachable when ActiveStorage::Blob attachable - when ActionDispatch::Http::UploadedFile + when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile ActiveStorage::Blob.create_after_upload! \ io: attachable.open, filename: attachable.original_filename, diff --git a/activestorage/lib/active_storage/attached/macros.rb b/activestorage/lib/active_storage/attached/macros.rb index 5779348148..027112195f 100644 --- a/activestorage/lib/active_storage/attached/macros.rb +++ b/activestorage/lib/active_storage/attached/macros.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ActiveStorage # Provides the class-level DSL for declaring that an Active Record model has attached blobs. module Attached::Macros @@ -10,25 +12,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 +51,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 @@ -81,4 +79,4 @@ module ActiveStorage end end end -end
\ No newline at end of file +end diff --git a/activestorage/lib/active_storage/attached/many.rb b/activestorage/lib/active_storage/attached/many.rb index 82989e4605..59b7d7d559 100644 --- a/activestorage/lib/active_storage/attached/many.rb +++ b/activestorage/lib/active_storage/attached/many.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ActiveStorage # Decorated proxy object representing of multiple attachments to a model. class Attached::Many < Attached @@ -5,7 +7,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 @@ -51,4 +53,3 @@ module ActiveStorage end end end - diff --git a/activestorage/lib/active_storage/attached/one.rb b/activestorage/lib/active_storage/attached/one.rb index 6b34b30f1c..2e5831348e 100644 --- a/activestorage/lib/active_storage/attached/one.rb +++ b/activestorage/lib/active_storage/attached/one.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ActiveStorage # Representation of a single attachment to a model. class Attached::One < Attached diff --git a/activestorage/lib/active_storage/engine.rb b/activestorage/lib/active_storage/engine.rb index da83d3908a..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 @@ -34,22 +36,21 @@ module ActiveStorage end initializer "active_storage.services" do - config.after_initialize do |app| - if config_choice = app.config.active_storage.service - config_file = Pathname.new(Rails.root.join("config/storage.yml")) - raise("Couldn't find Active Storage configuration in #{config_file}") unless config_file.exist? + config.to_prepare do + if config_choice = Rails.configuration.active_storage.service + configs = Rails.configuration.active_storage.service_configurations ||= begin + config_file = Pathname.new(Rails.root.join("config/storage.yml")) + raise("Couldn't find Active Storage configuration in #{config_file}") unless config_file.exist? - require "yaml" - require "erb" + require "yaml" + require "erb" - configs = - begin - YAML.load(ERB.new(config_file.read).result) || {} - rescue Psych::SyntaxError => e - raise "YAML syntax error occurred while parsing #{config_file}. " \ - "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \ - "Error: #{e.message}" - end + YAML.load(ERB.new(config_file.read).result) || {} + rescue Psych::SyntaxError => e + raise "YAML syntax error occurred while parsing #{config_file}. " \ + "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \ + "Error: #{e.message}" + end ActiveStorage::Blob.service = begin diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb index db79c669bf..bb6241ae47 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ActiveStorage # Returns the version of the currently loaded Active Storage as a <tt>Gem::Version</tt> def self.gem_version diff --git a/activestorage/lib/active_storage/log_subscriber.rb b/activestorage/lib/active_storage/log_subscriber.rb index 5c1b8d23ef..80cc5d5c80 100644 --- a/activestorage/lib/active_storage/log_subscriber.rb +++ b/activestorage/lib/active_storage/log_subscriber.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + require "active_support/log_subscriber" module ActiveStorage class LogSubscriber < ActiveSupport::LogSubscriber def service_upload(event) message = "Uploaded file to key: #{key_in(event)}" - message << " (checksum: #{event.payload[:checksum]})" if event.payload[:checksum] + message += " (checksum: #{event.payload[:checksum]})" if event.payload[:checksum] info event, color(message, GREEN) end diff --git a/activestorage/lib/active_storage/migration.rb b/activestorage/lib/active_storage/migration.rb deleted file mode 100644 index 2e35e163cd..0000000000 --- a/activestorage/lib/active_storage/migration.rb +++ /dev/null @@ -1,27 +0,0 @@ -class ActiveStorageCreateTables < ActiveRecord::Migration[5.1] - def change - create_table :active_storage_blobs do |t| - t.string :key - t.string :filename - t.string :content_type - t.text :metadata - t.integer :byte_size - t.string :checksum - t.datetime :created_at - - 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.datetime :created_at - - t.index :blob_id - t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true - end - end -end diff --git a/activestorage/lib/active_storage/service.rb b/activestorage/lib/active_storage/service.rb index eb25e9f001..ce736b8728 100644 --- a/activestorage/lib/active_storage/service.rb +++ b/activestorage/lib/active_storage/service.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_storage/log_subscriber" module ActiveStorage @@ -59,43 +61,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 c2e1b25a43..d066deaa20 100644 --- a/activestorage/lib/active_storage/service/azure_storage_service.rb +++ b/activestorage/lib/active_storage/service/azure_storage_service.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + require "active_support/core_ext/numeric/bytes" require "azure/storage" 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 @@ -57,11 +59,12 @@ module ActiveStorage end end - def url(key, expires_in:, disposition:, filename:) + def url(key, expires_in:, disposition:, filename:, content_type:) instrument :url, key do |payload| base_url = url_for(key) generated_url = signer.signed_uri(URI(base_url), false, permissions: "r", - expiry: format_expiry(expires_in), content_disposition: "#{disposition}; filename=\"#{filename}\"").to_s + expiry: format_expiry(expires_in), content_type: content_type, + content_disposition: "#{disposition}; filename=\"#{filename}\"").to_s payload[:url] = generated_url diff --git a/activestorage/lib/active_storage/service/configurator.rb b/activestorage/lib/active_storage/service/configurator.rb index 5d6475a8ae..39951fd026 100644 --- a/activestorage/lib/active_storage/service/configurator.rb +++ b/activestorage/lib/active_storage/service/configurator.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ActiveStorage class Service::Configurator #:nodoc: attr_reader :configurations diff --git a/activestorage/lib/active_storage/service/disk_service.rb b/activestorage/lib/active_storage/service/disk_service.rb index 3d92102cf0..cf4019966f 100644 --- a/activestorage/lib/active_storage/service/disk_service.rb +++ b/activestorage/lib/active_storage/service/disk_service.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + require "fileutils" require "pathname" 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 @@ -124,4 +126,3 @@ module ActiveStorage end end end - diff --git a/activestorage/lib/active_storage/service/gcs_service.rb b/activestorage/lib/active_storage/service/gcs_service.rb index ea4ec5a790..32dfb4851b 100644 --- a/activestorage/lib/active_storage/service/gcs_service.rb +++ b/activestorage/lib/active_storage/service/gcs_service.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + 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..39e922f7ab 100644 --- a/activestorage/lib/active_storage/service/mirror_service.rb +++ b/activestorage/lib/active_storage/service/mirror_service.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + 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 +22,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..98c9dd2972 100644 --- a/activestorage/lib/active_storage/service/s3_service.rb +++ b/activestorage/lib/active_storage/service/s3_service.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + require "aws-sdk" 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/active_storage/version.rb b/activestorage/lib/active_storage/version.rb index 8f45480712..4b6631832b 100644 --- a/activestorage/lib/active_storage/version.rb +++ b/activestorage/lib/active_storage/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "gem_version" module ActiveStorage diff --git a/activestorage/lib/tasks/activestorage.rake b/activestorage/lib/tasks/activestorage.rake index 1d386e67df..746bc5b28a 100644 --- a/activestorage/lib/tasks/activestorage.rake +++ b/activestorage/lib/tasks/activestorage.rake @@ -1,13 +1,8 @@ -require "fileutils" +# frozen_string_literal: true namespace :activestorage do desc "Copy over the migration needed to the application" - task :install do - migration_file_path = "db/migrate/#{Time.now.utc.strftime("%Y%m%d%H%M%S")}_active_storage_create_tables.rb" - FileUtils.mkdir_p Rails.root.join("db/migrate") - FileUtils.cp File.expand_path("../../active_storage/migration.rb", __FILE__), Rails.root.join(migration_file_path) - puts "Copied migration to #{migration_file_path}" - - puts "Now run rails db:migrate to create the tables for Active Storage" + task install: :environment do + Rake::Task["active_storage:install:migrations"].invoke end end |