> I was just getting edge Rails (2.3.0) running on Ruby 1.9.1preview2
> but ran into a problem with Rack.
s/with Rack//
> In the webrick handler (lib/rack/handler/webrick.rb), Rack is using
> a .each method when working with the headers (line 47). Unfortunately,
> Ruby 1.9 does not implement String#each so requests are unsuccessful
String bodies are evil, and should be punished. (Rails is wrong).
> I note that this technique is used in other handlers, however, so
> instead of submitting a patch when I am not particularly familiar with
> the Rack code base, I'm just letting you know so it can be factored in
> at some point - especially as it's a minor adjustment.
Specifically, the rack spec says:
=== The Body
The Body must respond to #each
and must only yield String values.
If the Body responds to #close, it will be called after iteration.
The Body commonly is an Array of Strings, the application
instance itself, or a File-like object.
Do not use String bodies in 1.9.
(The .each fix is useful for multiple header values. Future revisions of
Rack probably will use an explicit .split for these. This is yet to
be decided.)
--
Christian Neukirchen <chneuk...@gmail.com> http://chneukirchen.org
Rack used to expect and encourage String bodies because #each behaved
as expected.
>> In the webrick handler (lib/rack/handler/webrick.rb), Rack is using
>> a .each method when working with the headers (line 47). Unfortunately,
>> Ruby 1.9 does not implement String#each so requests are unsuccessful
>
> String bodies are evil, and should be punished. (Rails is wrong).
"Strings are no longer Enumerable, so we've deprecated their use as
response bodies. (Rails needs to be updated)."
>> I note that this technique is used in other handlers, however, so
>> instead of submitting a patch when I am not particularly familiar with
>> the Rack code base, I'm just letting you know so it can be factored in
>> at some point - especially as it's a minor adjustment.
>
> Specifically, the rack spec says:
>
> === The Body
> The Body must respond to #each
> and must only yield String values.
> If the Body responds to #close, it will be called after iteration.
> The Body commonly is an Array of Strings, the application
> instance itself, or a File-like object.
Which behaved as expected with older Rubies.
Many Rack apps use String bodies. Rack::Lint does not raise on String
bodies. Rack's own specs use String bodies.
Perhaps Rack should simply accept String bodies in 1.9 too?
jeremy
I think this is the right way to go. Even if you just alias each to
each_line in String on 1.9 it will work just fine.
Ezra
Right now in merb we use a StreamWrapper to wrap the response body
which in merb can be a string or a Proc or a file handle. If its a
proc we do the streaming dance and if it is a string we just call
string.each_line when each gets called by the rack handlers. This
allows for streaming and for steing bodies to work on 1.9
http://github.com/wycats/merb/tree/master/merb-core/lib/merb-core/rack/stream_wrapper.rb
Cheers-
Ezra Zygmuntowicz
e...@engineyard.com
Rails does the same. I'd love to see Rack take a more pragmatic stance
here, though!
http://github.com/rails/rails/tree/master/actionpack/lib/action_controller/rack_process.rb#L176
jeremy
Me too. So what is the best way for rack to behave here then? I guess
the smallest change for 1.9 compat is to have rack call each_line if
the body is_a? String. But I'd like to see a more comprehensive
approach that maybe moves what both rails and merb seem to be doing
down into the handlers?
-Ezra
if body.respond_to? :to_str
write body.to_str
elsif body.respond_to?(:each)
body.each { |part|
write part.to_s
}
else
raise TypeError, "stringable or iterable required"
end
Rack::Lint will raise on String bodies, if you use 1.9, no?
String bodies are a bad idea---they cause overhead for every line.
If you already have the whole string, just put it into an Array.
>
> On Wed, Dec 10, 2008 at 6:28 PM, Jeremy Kemper <jer...@bitsweat.net>
> wrote:
>> Many Rack apps use String bodies. Rack::Lint does not raise on String
>> bodies. Rack's own specs use String bodies.
>
> Rack::Lint will raise on String bodies, if you use 1.9, no?
>
> String bodies are a bad idea---they cause overhead for every line.
> If you already have the whole string, just put it into an Array.
Well plus it does an implicit split on the string. Also it's adversely
affected by ruby's magic globals.