Project

General

Profile

Actions

Feature #5479

closed

import StringIO into core, add String#to_io

Added by rkh (Konstantin Haase) about 13 years ago. Updated about 13 years ago.

Status:
Rejected
Assignee:
-
Target version:
[ruby-core:40312]

Description

Currently, a lot of APIs accept both String and IO instances. To differentiate what has been handed to those methods, the code often checks the object's class. However, from statements made by Matz at this years RubyConf it became clear that you should not rely on classes as contracts. Often, these projects wrap the String in a StringIO to avoid having two internal implementations.

It would be useful to add StringIO to core. This would allow adding a #to_io method to String (IO already implements #to_io).

An example use case:

WEBrick is one of those projects checking an objects class. Currently it is not possible to use Rails template streaming or the Sinatra streaming API with WEBrick, the de facto default server for both projects. If strings would implement #to_io, WEBrick would simply have to call #to_io on this. Rack/Sinatra/Rails could simply return an object that responds #to_io and in turn returns an object that behaves like IO, since creating a proper IO subclass that behaves properly and does not have a file handler is rather hard, especially if you want to support multiple Ruby versions (hence StringIO not inheriting from IO).


Files

noname (500 Bytes) noname Anonymous, 10/26/2011 02:23 AM
noname (500 Bytes) noname Anonymous, 10/26/2011 03:53 AM

Updated by nobu (Nobuyoshi Nakada) about 13 years ago

  • Status changed from Open to Rejected

You propose two different feature requests at once.

I reject the first one, "import StringIO into core", because it doesn't seem necessary.

I'm considering the second one.

Updated by headius (Charles Nutter) about 13 years ago

I assume the IO produced from a StringIO would not have a real file descriptor, since...it doesn't have a real file descriptor.

Could be done in JRuby using a ByteArrayInputStream. I'm not sure what it would mean to have read and write support though. Is that what's requested here? A pseudo-IO that reads from and writes to an area of memory?

public class RubyStringIO extends RubyObject {
@JRubyMethod
public IRubyObject to_io(ThreadContext context) {
return new RubyIO(context.runtime, new ByteArrayInputStream(data.internal.getBytes()));
}

Updated by Anonymous about 13 years ago

On Tue, Oct 25, 2011 at 10:14:54PM +0900, Charles Nutter wrote:

Issue #5479 has been updated by Charles Nutter.

I assume the IO produced from a StringIO would not have a real file descriptor, since...it doesn't have a real file descriptor.

Could be done in JRuby using a ByteArrayInputStream. I'm not sure what it would mean to have read and write support though. Is that what's requested here? A pseudo-IO that reads from and writes to an area of memory?

Yes, that's exactly what it is. JRuby already implements StringIO from
stdlib. I think Konstantin is just asking for:

  1. You don't need to require stringio for it to be available

  2. An implementation of to_io on String like this:

class String
def to_io; StringIO.new self; end
end

--
Aaron Patterson
http://tenderlovemaking.com/

Updated by rkh (Konstantin Haase) about 13 years ago

My main request was to add String#to_io, as Aaron described, so this protocol can actually be used. This is the only reason why I proposed moving StringIO to core. We could also add String#to_io as a monkey-patch to String in stringio in the stdlib.

Konstantin

On Oct 25, 2011, at 10:05 , Aaron Patterson wrote:

On Tue, Oct 25, 2011 at 10:14:54PM +0900, Charles Nutter wrote:

Issue #5479 has been updated by Charles Nutter.

I assume the IO produced from a StringIO would not have a real file descriptor, since...it doesn't have a real file descriptor.

Could be done in JRuby using a ByteArrayInputStream. I'm not sure what it would mean to have read and write support though. Is that what's requested here? A pseudo-IO that reads from and writes to an area of memory?

Yes, that's exactly what it is. JRuby already implements StringIO from
stdlib. I think Konstantin is just asking for:

  1. You don't need to require stringio for it to be available

  2. An implementation of to_io on String like this:

class String
def to_io; StringIO.new self; end
end

--
Aaron Patterson
http://tenderlovemaking.com/

Updated by Anonymous about 13 years ago

On Wed, Oct 26, 2011 at 02:22:21AM +0900, Haase, Konstantin wrote:

My main request was to add String#to_io, as Aaron described, so this protocol can actually be used. This is the only reason why I proposed moving StringIO to core. We could also add String#to_io as a monkey-patch to String in stringio in the stdlib.

I really like this idea, but I'm kind of afraid of the consequences.
StringIO isn't a subclass of IO, and some things in ruby call to_io
then check the return type:

irb(main):001:0> require 'stringio'
=> true
irb(main):002:0> File.exist? 'hello!'
=> false
irb(main):003:0> class String; def to_io; StringIO.new self; end end
=> nil
irb(main):004:0> File.exist? 'hello!'
TypeError: can't convert String to IO (String#to_io gives StringIO)
from (irb):4:in exist?' from (irb):4 from /Users/aaron/.local/bin/irb:12:in '
irb(main):005:0>

I'm not sure which is best: convert StringIO to subclass IO, or find
these places that call to_io and fix them. Not to mention, how do we
"fix" the above example? What does exists? mean in terms of a
StringIO?

--
Aaron Patterson
http://tenderlovemaking.com/

Updated by headius (Charles Nutter) about 13 years ago

On Tue, Oct 25, 2011 at 1:35 PM, Aaron Patterson
wrote:

On Wed, Oct 26, 2011 at 02:22:21AM +0900, Haase, Konstantin wrote:

My main request was to add String#to_io, as Aaron described, so this protocol can actually be used. This is the only reason why I proposed moving StringIO to core. We could also add String#to_io as a monkey-patch to String in stringio in the stdlib.

Oops, I totally spaced that off. Yeah, that's easy enough.

I really like this idea, but I'm kind of afraid of the consequences.
StringIO isn't a subclass of IO, and some things in ruby call to_io
then check the return type:
...
I'm not sure which is best: convert StringIO to subclass IO, or find
these places that call to_io and fix them.  Not to mention, how do we
"fix" the above example?  What does exists? mean in terms of a
StringIO?

I no longer like the idea myself :) It feels too much to me like
to_str and to_ary and seems to have the same "internals" implications
they do: that they'll return a subclass of that type.

  • Charlie

Updated by headius (Charles Nutter) about 13 years ago

On Tue, Oct 25, 2011 at 1:56 PM, Haase, Konstantin
wrote:

Maybe another idea would be to introduce a Streamable protocol/class/module, and add a to_stream method both to IO and StringIO. It could also ease implementing your own IO-like behavior.

This is not without precedent: JRuby's IO has to_ methods to aid Java
integration: to_inputstream, to_outputstream, and to_channel. And
Java's InputStream, OutputStream, and Channel classes are decorated
with to_io.

  • Charlie
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0