Rake task for syntax checking a Ruby on Rails project

Posted by warren
on Wednesday, June 04

Here's a quick rake file that will crawl through your Rails project and syntax check ruby, erb, and yml files. You should always run this before doing a "cap deploy" and it even doesn't hurt to run it before a "svn commit".

require 'erb'
require 'open3'
require 'yaml'

task :check_syntax => [:check_ruby, :check_erb, :check_yaml]

task :check_erb do
  (Dir["**/*.erb"] + Dir["**/*.rhtml"]).each do |file|
    next if file.match("vendor/rails")
    Open3.popen3('ruby -c') do |stdin, stdout, stderr|
      stdin.puts(ERB.new(File.read(file), nil, '-').src)
      stdin.close
      if error = ((stderr.readline rescue false))
        puts file + error[1..-1]
      end
      stdout.close rescue false
      stderr.close rescue false
    end
  end
end

task :check_ruby do
  Dir['**/*.rb'].each do |file|
    next if file.match("vendor/rails")
    next if file.match("vendor/plugins/.*/generators/.*/templates")
    Open3.popen3("ruby -c #{file}") do |stdin, stdout, stderr|
      if error = ((stderr.readline rescue false))
        puts error
      end
      stdin.close rescue false
      stdout.close rescue false
      stderr.close rescue false
    end
  end
end

task :check_yaml do
  Dir['**/*.yml'].each do |file|
    next if file.match("vendor/rails")
    begin
      YAML.load_file(file)
    rescue => e
      puts "#{file}:#{(e.message.match(/on line (\d+)/)[1] + ':') rescue nil} #{e.message}"
    end
  end
end

And here's what the output looks like:

warren:tmp_project$ rake check_syntax
(in /Users/warren/tmp_project)
app/controllers/application.rb:37: syntax error, unexpected '='
app/views/people/home.html.erb:60: syntax error, unexpected '<', expecting $end
vendor/plugins/will_paginate/test/fixtures/users.yml:13: syntax error on line 13, col 0: `dev_<%= digit %>:'

This could probably be expanded to support lots of other types of files as well (css, javascripts, etc).

Updates:

  • Exclude all files in vendor/rails (thanks szeryf)
Comments

Leave a response

  1. Joe GrossbergJune 04, 2008 @ 01:13 PM
    Ooh, interesting. How would this approach work for CSS though, since it's not executed? Are you talking about using a W3C validator or the like?
  2. Dan MangesJune 04, 2008 @ 08:06 PM
    Wouldn't it be much better to use tests? At least for the .rb and .erb files.
  3. Chris BaileyJune 05, 2008 @ 01:35 AM
    Pretty cool. I ran it on my current project, which uses Edge Rails/Rails 2.1, and every single error it spit out was from vendor/rails :)
  4. szeryfJune 05, 2008 @ 04:58 AM
    If you have Rails in vendor/rails, you might want to skip it in checking too. To do this, change the line 23 (3rd line of task :check_ruby) to: next if file.match("vendor/.*/generators/.*/templates") It also barfs on several Rails yml files, so I added the following before line 37 (3rd line of task :check_yml): next if file.match("vendor/rails") Other than that, it's really cool! :)
  5. WarrenJune 05, 2008 @ 09:27 AM
    Joe: I haven't found one yet, but I would imagine that there is a regular expression that describes valid syntax for a CSS file. Syntax checking would simply be a matter of checking each .css file against this regexp. Hitting the W3C service would most likely be very slow. Dan: Test don't necessarily cover every single file in your project. Chris/szeryf: I hadn't thought of skipping vendor/rails... great idea! I've updated the post to reflect that! Skipping vendor/rails should also speed this task up significantly.
  6. Adam BairJune 05, 2008 @ 06:33 PM
    Using it now... Look at that, it's already found some ugly. I set it up to ignore vendor/plugins as well as vendor/rails. Thanks guys, nice work!
  7. anonymousJune 26, 2008 @ 12:29 PM
    Wouldn't it be better to just use flog or heckle?
  8. Michael FairchildAugust 18, 2008 @ 02:46 PM
    Thanks, on the first run I found an error in my project. Much better me than someone else. I'll be using this all the time now.
  9. Morten ChristensenOctober 25, 2008 @ 05:23 AM
    RailsCheck (http://railscheck.rubyforge.org/) do all this and more.
  10. WikkiNovember 18, 2008 @ 01:54 AM
    Nice thing, I am going to use it...
Comment