Ruby Syntax Checker using Open3

I recently needed to write code to check Ruby syntax. The Open3 library made it trivial. From the RDoc:

Open3 grants you access to stdin, stdout, and stderr when running another program.

Here's the code for the syntax checker. I also added an example of using Open3 with wc to print out how many lines of code the file contained.

require "open3"

class SyntaxChecker
  def self.check(ruby)
    Open3.popen3 "ruby -wc" do |stdin, stdout, stderr|
      stdin.write ruby
      stdin.close
      output = stdout.read
      errors = stderr.read
      SyntaxCheckResult.new(output.any? ? output : errors)
    end
  end
end

class SyntaxCheckResult
  def initialize(output)
    @valid = (output == "Syntax OK\n")
    @output = output
  end
  
  def line_of_error
    $1.to_i if @output =~ /^-:(\d+):/
  end
  
  def valid?
    @valid
  end
end

l, w, c = Open3.popen3 "wc" do |stdin, stdout, stderr|
  stdin.write File.read($0)
  stdin.close
  stdout.read.split
end
puts "This file contains #{l} lines, #{w} words, and #{c} characters."

if __FILE__ == $0
  require "test/unit"
  
  class SyntaxCheckerTest < Test::Unit::TestCase    
    def test_valid_syntax
      result = SyntaxChecker.check "this.is.valid.syntax"
      assert_equal true, result.valid?
    end
    
    def test_invalid_syntax
      result = SyntaxChecker.check "this.is -> not -> valid $ruby:syntax"
      assert_equal false, result.valid?
    end
    
    def test_invalid_syntax_line_number
      result = SyntaxChecker.check "line(1).is.okay\nline(2) is not :("
      assert_equal 2, result.line_of_error
    end
  end
end

Also see POpen4:

POpen4 provides the Rubyist a single API across platforms for executing a command in a child process with handles on stdout, stderr, stdin streams as well as access to the process ID and exit status.