require 'action_controller' module FileBlobs # Module mixed into ActionController::DataStreaming. module ActionControllerDataStreamingExtensions ETAG = 'ETag'.freeze HTTP_IF_NONE_MATCH = 'HTTP_IF_NONE_MATCH'.freeze # Sends a file blob to the browser. # # This method uses HTTP's strong etag feature to facilitate serving the files # from a cache whenever possible. # # @param [FileBlobs::FileBlobProxy] proxy a proxy for a collection of # attributes generated by has_file_blob # @param [Hash] options tweaks the options passed to the # underlying send_data call; this method sets the :filename and :type # options, but their values can be overridden by the options hash # @see ActionController::DataStreaming#send_data def send_file_blob(proxy, options = {}) if request.get_header(HTTP_IF_NONE_MATCH) == proxy.blob_id head :not_modified else response.headers[ETAG] = proxy.blob_id send_options = { type: proxy.mime_type, filename: proxy.original_name } send_options.merge! options send_data proxy.data, send_options end end # Creates the table used to hold file blobs. # # @param [Symbol] table_name the name of the table used to hold file data # @param [Hash] options # @option options [Boolean] null true # @option options [Integer] blob_limit the maximum file size that can be # stored in the table; defaults to 1 megabyte def file_blob(column_name_base = :file, options = {}, &block) allow_null = options[:null] || false mime_type_limit = options[:mime_type_limit] || 64 file_name_limit = options[:file_name_limit] || 256 # The index is needed for garbage-collection eligibility checks. string :"#{column_name_base}_blob_id", limit: 48, null: allow_null, index: true integer :"#{column_name_base}_size", null: allow_null string :"#{column_name_base}_mime_type", limit: mime_type_limit, null: allow_null string :"#{column_name_base}_original_name", limit: file_name_limit, null: allow_null end end # module FileBlobs::ActionControllerDataStreamingExtensions end # namespace FileBlobs ActionController::DataStreaming.class_eval do include FileBlobs::ActionControllerDataStreamingExtensions end