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<Symbol, Object>] 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
end  # module FileBlobs::ActionControllerDataStreamingExtensions

end  # namespace FileBlobs

ActionController::DataStreaming.class_eval do
  include FileBlobs::ActionControllerDataStreamingExtensions
end

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<Symbol, Object>] 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
  protected :send_file_blob
end  # module FileBlobs::ActionControllerDataStreamingExtensions

end  # namespace FileBlobs

ActionController::DataStreaming.class_eval do
  include FileBlobs::ActionControllerDataStreamingExtensions
end

Make send_file_blob protected, because send_data is also protected.
Make send_file_blob protected, because send_data is also protected.
