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?
Excerpts from Daniele S.'s message of 2014-02-12 17:17:32 +0100:
Dir["**/*.erb"].each do |template|
binding in result() causing the evaluation of the template to fail
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’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.