Rails has its own capture method but I’ve often needed to capture the output in a Ruby script, mainly for unit testing purposes. It is pretty easy:
require 'stringio'
# redirect output to StringIO objects
stdout, stderr = StringIO.new, StringIO.new
$stdout, $stderr = stdout, stderr
# output is captured
puts 'foo'
warn 'bar'
# restore normal output
$stdout, $stderr = STDOUT, STDERR
stdout.string.match /foo/ #=> true
stderr.string.match /bar/ #=> true
I like to wrap this to make it a bit more practical:
require 'stringio'
require 'ostruct'
class Capture
def self.capture &block
# redirect output to StringIO objects
stdout, stderr = StringIO.new, StringIO.new
$stdout, $stderr = stdout, stderr
result = block.call
# restore normal output
$stdout, $stderr = STDOUT, STDERR
OpenStruct.new(
result: result,
stdout: stdout.string,
stderr: stderr.string
)
end
end
c = Capture.capture do
puts 'foo'
warn 'bar'
end
c.stdout.match 'foo' #=> true
c.stderr.match 'bar' #=> true