Check your scripts with JSLint on Rails
by Jakub Suder
29 March 2010
In 2009, I worked on two major projects at Lunar Logic Polska, HabitatMap and Hapnin. Both of these involved quite a lot of Javascript code – to such an extent that sometimes there was much more complexity and work involved on the Javascript side than on the Rails side.
When you write so much Javascript code, you need to start taking the language seriously and make sure that you follow the same kinds of best practices that you do with your Rails code – otherwise, your Javascript will quickly become unreadable and difficult to maintain, and the bug count will increase exponentially. In Hapnin, I used the Blue Ridge library, which combines a Javascript testing framework (Screw.Unit), mocking library (Smoke), Rhino and EnvJs (for testing in the console) in an easy to use Rails plugin.
There are however some specific kinds of errors that can be detected much easier, automatically, without having to write
any unit tests, and which could be missed completely by the testing suite. Things like a comma at the end of a hash
definition (e.g. { a: 1, b: 2, }) – this would pass any Blue Ridge spec, but would crash the site in Internet
Explorer, or '==' operator used in a place where '===' is more appropriate – which you probably wouldn't find
unless you knew what to look for.
Luckily, there is a tool that can find these kinds of errors, a tool that most web developers probably have heard about, but which few of them actually use. It's called JSLint and was written by Douglas Crockford 8 years ago.
I think one of the reasons why Rails developers don't use JSLint often – apart from not knowing about it, or not realizing that it can be useful – is that it isn't as easy to install and use as Rails testing frameworks like Test::Unit or RSpec. Instead of installing a gem or plugin and calling a rake task, you have to download and install it manually in the system, or use some other package manager like MacPorts.
I looked for any Ruby libraries that would wrap JSLint into something more convenient for a Rails developer, but I couldn't find any – so I've decided to write one. JSLint on Rails is a Rails plugin, and it contains everything you need to check your code with JSLint – JSLint itself, Rhino Javascript engine and some Rake tasks; the only thing you may need to install manually is Java JRE (required for running Rhino), but you probably already have that.
Here's how you use it:
- Make sure you have Java installed.
- Install the plugin:
./script/plugin install git://github.com/psionides/jslint_on_rails.git - Run the rake task:
rake jslint - Optionally, add
rake jslintto your continuous integration build to make sure it's run automatically.
When you call rake jslint, you will get a result like this (if everything goes well):
Running JSLint:
checking public/javascripts/Event.js... OK
checking public/javascripts/Map.js... OK
checking public/javascripts/Marker.js... OK
checking public/javascripts/Reports.js... OK
No JS errors found.
If something is wrong, you will get such results instead:
Running JSLint:
checking public/javascripts/Event.js... 2 errors:
Lint at line 24 character 15: Use '===' to compare with 'null'.
if (a == null && b == null) {
Lint at line 72 character 6: Extra comma.
},
checking public/javascripts/Marker.js... 1 error:
Lint at line 275 character 27: Missing radix parameter.
var x = parseInt(mapX);
Found 3 errors.
rake aborted!
JSLint test failed.
The plugin has also a configuration file, config/jslint.yml, which is created for you during the installation. You'll
want to take a look at it, especially to change the “paths” and “exclude_paths” options that tell it which files to
check – I'm pretty sure you don't want it to check entire jQuery or Prototype each time, just your own code. You can
also set all JSLint options in that file – I've set the defaults to what I
believed was reasonable, but feel free to tweak them if you disagree. I've also added a few custom options to silence
some types of warnings which I find annoying – you'll find these at the end of the config file, disabled by
default.
If you use a different Ruby web framework (e.g. Merb or Sinatra), or you just don't want to use Rails plugins for some reason, JSLint on Rails can also be used as a plain Ruby gem. To do that, you need to:
- Install the gem (
gem install jslint_on_rails, or via bundler). - Include JSLint's tasks in your Rakefile:
require 'jslint/tasks' - Also in the Rakefile, set path to your config file:
JSLint.config_path = "config/jslint.yml"(anything you want actually) - Create a sample config:
rake jslint:copy_config
After that, you can update your config and run the test with rake jslint.
- Project page on GitHub: http://github.com/psionides/jslint_on_rails
- Original JSLint project page: http://jslint.com