2
\$\begingroup\$

I'd like to refactor the following code:

case @request.path
when '/'
  Rack::Response.new do |response|
    do_stuff
  end
when '/env' then Rack::Response.new(@env.to_html)
end

And extract Rack::Response.new, something like the following:

Rack::Response.new case @request.path
when '/'    then Proc.new {|response| do_stuff }
when '/env' then @env.to_html
end

But I get

stringable or iterable required

What's the correct implementation (Ruby 1.9.2)?

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Essentially, you are wanting Ruby Procs to be first-class. By design, this language prefers other ways to accomplish your objective.

I see Rack::Response.new's first argument is the response body.

Looking at Rack::Response, you can do something like:

rr = Rack::Response.new
body = ''
block = Proc.new {}

case @request.path
when '/'
  block = Proc.new {|response| do_stuff }
when '/env'
  body = @env.to_html
end

rr.write body
rr.finish &block

Wrapping up rr, block and body into whatever object you wish would improve this further.

\$\endgroup\$
2
\$\begingroup\$

In order to pass a block to a function, you need to prefix it with an ampersand.

block_or_string = case @request.path
  when '/'    then Proc.new { |response| do_stuff }
  when '/env' then @end.to_html
end

response = if block_or_string.is_a?(Proc)
  Rack::Response.new(&block_or_string)
else
  Rack::Response.new(block_or_string)
end

This is pretty ugly. It might be an improvement to wrap the strings in simple procs.

block = case @request.path
  when '/'    then Proc.new { |response| do_stuff }
  when '/env' then Proc.new { @end.to_html }
end

Rack::Response.new(&block)
\$\endgroup\$
1
  • 1
    \$\begingroup\$ However, Rack::Response.new responds differently to a block than to the first argument. It would work if you changed the line to: when '/env' then Proc.new { rr.write @end.to_html }, but it's complicated. \$\endgroup\$ Commented Jan 23, 2012 at 16:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.