From be7392ddc2ea8b7d0c24fc7a7096174a95bdf574 Mon Sep 17 00:00:00 2001 From: Per Lundberg Date: Tue, 21 Nov 2017 15:21:43 +0200 Subject: [PATCH] UploadedFile: Handle content being a Pathname (#210) * UploadedFile: Handle content being a Pathname Dynamic languages... Can't live with them, can't live without them. In #149, we added support for `UploadedFile` being an `StringIO `object, by means of the `if content.respond_to?(:read)` logic. _However_, that had the unintended consequence of breaking the use case when a `Pathname` is provided instead of a string as the `content` paramer, since a `Pathname` _also_ responds to the `read` message... This PR works around that, by adding some extra checking. As an added bonus, I also added some YARD comments to make it more clear what parameter types this method expects/accepts. Fixes #207. * Peer suggestion: Invert check to make the code safer. --- lib/rack/test/uploaded_file.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/rack/test/uploaded_file.rb b/lib/rack/test/uploaded_file.rb index 13a9245a..a348f0fa 100644 --- a/lib/rack/test/uploaded_file.rb +++ b/lib/rack/test/uploaded_file.rb @@ -1,5 +1,6 @@ -require 'tempfile' require 'fileutils' +require 'pathname' +require 'tempfile' module Rack module Test @@ -18,8 +19,16 @@ class UploadedFile # The content type of the "uploaded" file attr_accessor :content_type + # Creates a new UploadedFile instance. + # + # @param content [IO, Pathname, String, StringIO] a path to a file, or an {IO} or {StringIO} object representing the + # file. + # @param content_type [String] + # @param binary [Boolean] an optional flag that indicates whether the file should be open in binary mode or not. + # @param original_filename [String] an optional parameter that provides the original filename if `content` is an IO + # object. def initialize(content, content_type = 'text/plain', binary = false, original_filename: nil) - if content.respond_to?(:read) + if content.respond_to?(:read) && (content.is_a?(IO) || content.is_a?(StringIO)) initialize_from_io(content, original_filename) else initialize_from_file_path(content)