tags:

views:

304

answers:

3

I'm preparing a string that will be eval'ed. The string will contain a clause built from an existing Array. I have the following:

def stringify(arg)
    return "[ '" + arg.join("', '") + "' ]" if arg.class == Array
    "'#{arg}'"
end

a = [ 'a', 'b', 'c' ]
eval_str = 'p ' + stringify(a)
eval(eval_str)

which prints the string ["a", "b", "c"].

Is there a more idiomatic way to do this? Array#to_s doesn't cut it. Is there a way to assign the output from the p method to a variable?

Thanks!

A: 

I may be misunderstanding you, but does this look better at all?

>> a = %w[a b c]
=> ["a", "b", "c"]
>> r = "['#{a.join("', '")}']"
=> "['a', 'b', 'c']"
>> r.class
=> String

I suppose I'm confused by the need for eval, unless that's a part of something outside of what I see here.

dylanfm
+7  A: 

inspect should accomplish what you are wanting.

>> a = %w(a b c)
=> ["a", "b", "c"]
>> a.inspect
=> "[\"a\", \"b\", \"c\"]"
Aaron Hinni
inspect is perfect. Thanks!@dylanfm, yes eval was for context only.
Martin Carpenter
A: 

Is there a way to assign the output from the p method to a variable?

p (the same as puts) writes it's argument to $stdout and returns nil. To capture this output, you need to temporarily redefine $stdout.

require 'stringio'

def capture_stdout
  old = $stdout
  $stdout = StringIO.new(output = "")
  begin
    yield
  ensure 
    # Wrapping this in ensure means $stdout will 
    # be restored even if an exception is thrown
    $stdout = old
  end
  output
end

output = capture_stdout do
  p "Hello"
end

output # => "Hello"

I am not sure why you need this in the example, you could just do

output = stringify(a)