Excerpts from Daniele Sluijters's message of 2014-02-12 17:17:32 +0100:
> I'm trying to implement a Rake task that will syntax validate an ERB
> template. Up to now I was always able to do this with "erb -P -x -T '-'
> /path/to/template | ruby -c" on the command line but doing this
> individually for a lot of files becomes slow pretty quickly.
> 
> I'd hoped to implement this in Ruby and so far I'v got this:
> 
> 
> error_string = ""
> failures = 0
> Dir["**/*.erb"].each do |template|
>     begin
>         ERB.new(File.read(File.expand_path(template)), nil, '-').result
>     rescue SyntaxError => e
>         error_string += "Template Error on #{template}: #{e.message}\n"
>         failures += 1
>     end
> end
> 
> 
> Unfortunately this blows up fairly explosively since I'm not providing a
> binding in result() causing the evaluation of the template to fail
> because different variables that have things done to them in the
> template are now nil so a lot of method calls fail.
> 
> Looking at some of the ERB code I figured I could try run() to with and
> without passing on TOPLEVEL_BINDING.taint but that didn't change
> anything. I have no idea what TOPLEVEL_BINDING.taint is supposed to do
> in the first place or how that would magically solve the issue.
> 
> However, the command line seems to be able to get past this issue and
> just check the syntax, not try to evaluate the template but I can't seem
> to replicate that. I was curious if someone knew what I need to do to
> fix this?
> 

You can look at what the `erb` command does, as it's just a ruby script. From
it, you'll see that it basically calls ERB#src, so that's the way to retrieve
the ruby code. The only problem lies in having ruby check the syntax of the
file. Unfortunately, as far as I know, there's no simple way to do that from
inside ruby itself. I guess you could try writing the result of ERB#src to a
file, then load it (perhaps passing true as second argument to load) and check
for SyntaxError, but I think that would be slow. I think the best approach, is
to use Ripper (at least if you're using ruby 1.9). It is not documented, but it
seems that Ripper.sexp returns nil if there are syntax errors and an array if
the syntax is correct. With this approach, you loose the error message, since
Ripper.sexp doesn't give any. If you need them, you can use your original
approach calling ruby -c, but only on the incorrect files (as I guess there
won't be many incorrect files, this shouldn't slow things down too much).

Putting everything together, this is how I'd do it:

require 'ripper'

error_string = ""
failures = 0
Dir["**/*.erb"].each do |template|
     begin
		     file = File.expand_path template
         src = ERB.new(File.read(file), nil, '-').src
				 if !Ripper.sexp(src)
				   error_string += `erb -P -x -T '-' #{file} | ruby -c 2>&1` + "\n"
           failures += 1
  			 end
     end
 end
  
I hope this helps

Stefano