diff options
Diffstat (limited to 'activestorage/lib')
-rw-r--r-- | activestorage/lib/active_storage.rb | 1 | ||||
-rw-r--r-- | activestorage/lib/active_storage/analyzer/video_analyzer.rb | 4 | ||||
-rw-r--r-- | activestorage/lib/active_storage/attached/macros.rb | 12 | ||||
-rw-r--r-- | activestorage/lib/active_storage/engine.rb | 10 | ||||
-rw-r--r-- | activestorage/lib/active_storage/previewer.rb | 17 | ||||
-rw-r--r-- | activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb | 2 | ||||
-rw-r--r-- | activestorage/lib/active_storage/reflection.rb | 64 | ||||
-rw-r--r-- | activestorage/lib/active_storage/service.rb | 4 | ||||
-rw-r--r-- | activestorage/lib/active_storage/service/gcs_service.rb | 1 |
9 files changed, 102 insertions, 13 deletions
diff --git a/activestorage/lib/active_storage.rb b/activestorage/lib/active_storage.rb index e1deee1d82..928db32691 100644 --- a/activestorage/lib/active_storage.rb +++ b/activestorage/lib/active_storage.rb @@ -49,4 +49,5 @@ module ActiveStorage mattr_accessor :paths, default: {} mattr_accessor :variable_content_types, default: [] mattr_accessor :content_types_to_serve_as_binary, default: [] + mattr_accessor :service_urls_expire_in, default: 5.minutes end diff --git a/activestorage/lib/active_storage/analyzer/video_analyzer.rb b/activestorage/lib/active_storage/analyzer/video_analyzer.rb index e31bdb0edb..18d8ff8237 100644 --- a/activestorage/lib/active_storage/analyzer/video_analyzer.rb +++ b/activestorage/lib/active_storage/analyzer/video_analyzer.rb @@ -16,7 +16,7 @@ module ActiveStorage # # When a video's angle is 90 or 270 degrees, its width and height are automatically swapped for convenience. # - # This analyzer requires the {ffmpeg}[https://www.ffmpeg.org] system library, which is not provided by Rails. + # This analyzer requires the {FFmpeg}[https://www.ffmpeg.org] system library, which is not provided by Rails. class Analyzer::VideoAnalyzer < Analyzer def self.accept?(blob) blob.video? @@ -107,7 +107,7 @@ module ActiveStorage JSON.parse(output.read) end rescue Errno::ENOENT - logger.info "Skipping video analysis because ffmpeg isn't installed" + logger.info "Skipping video analysis because FFmpeg isn't installed" {} end diff --git a/activestorage/lib/active_storage/attached/macros.rb b/activestorage/lib/active_storage/attached/macros.rb index f99cf35680..6ad9fc43d7 100644 --- a/activestorage/lib/active_storage/attached/macros.rb +++ b/activestorage/lib/active_storage/attached/macros.rb @@ -48,6 +48,12 @@ module ActiveStorage else before_destroy { public_send(name).detach } end + + ActiveRecord::Reflection.add_attachment_reflection( + self, + name, + ActiveRecord::Reflection.create(:has_one_attached, name, nil, { dependent: dependent }, self) + ) end # Specifies the relation between multiple attachments and the model. @@ -105,6 +111,12 @@ module ActiveStorage else before_destroy { public_send(name).detach } end + + ActiveRecord::Reflection.add_attachment_reflection( + self, + name, + ActiveRecord::Reflection.create(:has_many_attached, name, nil, { dependent: dependent }, self) + ) end end end diff --git a/activestorage/lib/active_storage/engine.rb b/activestorage/lib/active_storage/engine.rb index 99588cdd4b..93c5c55b95 100644 --- a/activestorage/lib/active_storage/engine.rb +++ b/activestorage/lib/active_storage/engine.rb @@ -10,6 +10,8 @@ require "active_storage/previewer/video_previewer" require "active_storage/analyzer/image_analyzer" require "active_storage/analyzer/video_analyzer" +require "active_storage/reflection" + module ActiveStorage class Engine < Rails::Engine # :nodoc: isolate_namespace ActiveStorage @@ -52,6 +54,7 @@ module ActiveStorage ActiveStorage.variable_content_types = app.config.active_storage.variable_content_types || [] ActiveStorage.content_types_to_serve_as_binary = app.config.active_storage.content_types_to_serve_as_binary || [] + ActiveStorage.service_urls_expire_in = app.config.active_storage.service_urls_expire_in || 5.minutes end end @@ -95,5 +98,12 @@ module ActiveStorage end end end + + initializer "active_storage.reflection" do + ActiveSupport.on_load(:active_record) do + include Reflection::ActiveRecordExtensions + ActiveRecord::Reflection.singleton_class.prepend(Reflection::ReflectionExtension) + end + end end end diff --git a/activestorage/lib/active_storage/previewer.rb b/activestorage/lib/active_storage/previewer.rb index bff5e42d41..fb202f029a 100644 --- a/activestorage/lib/active_storage/previewer.rb +++ b/activestorage/lib/active_storage/previewer.rb @@ -31,7 +31,7 @@ module ActiveStorage # Executes a system command, capturing its binary output in a tempfile. Yields the tempfile. # - # Use this method to shell out to a system library (e.g. mupdf or ffmpeg) for preview image + # Use this method to shell out to a system library (e.g. muPDF or FFmpeg) for preview image # generation. The resulting tempfile can be used as the +:io+ value in an attachable Hash: # # def preview @@ -44,16 +44,17 @@ module ActiveStorage # # The output tempfile is opened in the directory returned by #tempdir. def draw(*argv) #:doc: - ActiveSupport::Notifications.instrument("preview.active_storage") do - open_tempfile_for_drawing do |file| + open_tempfile do |file| + instrument :preview, key: blob.key do capture(*argv, to: file) - yield file end + + yield file end end - def open_tempfile_for_drawing - tempfile = Tempfile.open("ActiveStorage", tempdir) + def open_tempfile + tempfile = Tempfile.open("ActiveStorage-", tempdir) begin yield tempfile @@ -62,6 +63,10 @@ module ActiveStorage end end + def instrument(operation, payload = {}, &block) + ActiveSupport::Notifications.instrument "#{operation}.active_storage", payload, &block + end + def capture(*argv, to:) to.binmode IO.popen(argv, err: File::NULL) { |out| IO.copy_stream(out, to) } diff --git a/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb b/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb index 2a787362cf..69eb617d7b 100644 --- a/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb +++ b/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb @@ -12,7 +12,7 @@ module ActiveStorage end def pdftoppm_exists? - return @pdftoppm_exists unless @pdftoppm_exists.nil? + return @pdftoppm_exists if defined?(@pdftoppm_exists) @pdftoppm_exists = system(pdftoppm_path, "-v", out: File::NULL, err: File::NULL) end diff --git a/activestorage/lib/active_storage/reflection.rb b/activestorage/lib/active_storage/reflection.rb new file mode 100644 index 0000000000..04a1b20882 --- /dev/null +++ b/activestorage/lib/active_storage/reflection.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module ActiveStorage + module Reflection + # Holds all the metadata about a has_one_attached attachment as it was + # specified in the Active Record class. + class HasOneAttachedReflection < ActiveRecord::Reflection::MacroReflection #:nodoc: + def macro + :has_one_attached + end + end + + # Holds all the metadata about a has_many_attached attachment as it was + # specified in the Active Record class. + class HasManyAttachedReflection < ActiveRecord::Reflection::MacroReflection #:nodoc: + def macro + :has_many_attached + end + end + + module ReflectionExtension # :nodoc: + def add_attachment_reflection(ar, name, reflection) + ar.attachment_reflections.merge!(name.to_s => reflection) + end + + private + def reflection_class_for(macro) + case macro + when :has_one_attached + HasOneAttachedReflection + when :has_many_attached + HasManyAttachedReflection + else + super + end + end + end + + module ActiveRecordExtensions + extend ActiveSupport::Concern + + included do + class_attribute :attachment_reflections, instance_writer: false, default: {} + end + + module ClassMethods + # Returns an array of reflection objects for all the attachments in the + # class. + def reflect_on_all_attachments + attachment_reflections.values + end + + # Returns the reflection object for the named +attachment+. + # + # User.reflect_on_attachment(:avatar) + # # => the avatar reflection + # + def reflect_on_attachment(attachment) + attachment_reflections[attachment.to_s] + end + end + end + end +end diff --git a/activestorage/lib/active_storage/service.rb b/activestorage/lib/active_storage/service.rb index da1af4f745..f915518f52 100644 --- a/activestorage/lib/active_storage/service.rb +++ b/activestorage/lib/active_storage/service.rb @@ -39,8 +39,6 @@ module ActiveStorage extend ActiveSupport::Autoload autoload :Configurator - class_attribute :url_expires_in, default: 5.minutes - class << self # Configure an Active Storage service by name from a set of configurations, # typically loaded from a YAML file. The Active Storage engine uses this @@ -92,7 +90,7 @@ module ActiveStorage 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+), + # of seconds specified in +expires_in+. You must 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 diff --git a/activestorage/lib/active_storage/service/gcs_service.rb b/activestorage/lib/active_storage/service/gcs_service.rb index 38acef81f4..fdde01d4a3 100644 --- a/activestorage/lib/active_storage/service/gcs_service.rb +++ b/activestorage/lib/active_storage/service/gcs_service.rb @@ -6,7 +6,6 @@ require "google/cloud/storage" require "net/http" require "active_support/core_ext/object/to_query" -require "active_storage/filename" module ActiveStorage # Wraps the Google Cloud Storage as an Active Storage service. See ActiveStorage::Service for the generic API |