Wednesday, January 4, 2012

Rails 3.1 "Could not find a JavaScript runtime" error

I just got my first Rails 3.1 on JRuby project created.  However I keep getting the error "Could not find a JavaScript runtime ..." when trying to do pretty much anything with it.  After digging in to this some, it turns out that with the addition of CoffeeScript in 3.1, Rails needs to run Javascript code natively.  A gem called execjs was added to Rails to allow this.  EXCEPT, execjs itself needs something else to actually evaluate the Javascript.    See https://github.com/sstephenson/execjs for a list.  If you're running in Mac or Windows, you're good, there are system libraries to do it.  But if you're in Linux, unless you have node.js installed, it won't work.

Let me repeat that.  Rails 3.1 apps by default will NOT work in Linux, unless you have node.js installed.  This is absolutely ridiculous... guess what Rails team, a lot of people are developing in Linux and not Mac.  I understand how stuff not working in Windows is released, but Linux??

So to get things to work you'll need to add one of the gems listed on the execjs page.  If you're running the MRI Ruby, just add:

gem 'therubyracer'

to your Gemfile.  I've read a lot of complaints about therubyracer.  But it appears to be the most popular.  If you're running JRuby like me, add:

gem 'therubyrhino'

to your Gemfile.  I've verified that this works correctly.

FOLLOW UP 1/13/2012:
See my comments.  I have made a fix to Rails to put the appropriate gem in the Gemfile if you are in Linux, and issued pull requests to the Rails core to incorporate this code.  They have made some comments on it, hopefully it will be pulled in to Rails soon.

4 comments:

Ben Atkin said...

I think that from the Rails developer perspective it's still *by default* if all you have to change is the Gemfile. To them it's not unlike having to ensure that ruby is installed in the first place.

Brent said...

The Ruby on Rails download page (http://rubyonrails.org/download) makes no mention of this, so to me it is not the same as assuming that Ruby is installed. Ideally Rails should check if there is a Javascript runtime on the system, and if not, add one to the Gemfile when a project is created. Hmmm, maybe I'll dig in to the Rails code and patch it to do this, and make a pull request. The only problem is deciding which gem to use, I've read bad things about therubyracer but that seems to be the most popular one.

Brent said...

I have made a fix to the Rails code and issued pull requests:
Rails master branch pull request (Rails 4.0) - https://github.com/rails/rails/pull/4435

Rails 3.2 branch pull request - https://github.com/rails/rails/pull/4437

Rails 3.1 branch pull request - https://github.com/rails/rails/pull/4436

There are some discussions going on about this. I had originally added the same runtime detection that execjs does, however the core team did not think it was appropriate for Rails to do this. So these pull requests assume that Linux always needs therubyracer gem. I think this is OK, because Rails should not be relying on node.js.

Brent said...

So the Rails core team rejected my change. This issue went all the way up to tenderlove who is one of the key maintainers. I just don't understand why they don't see this as something needing fixed.

However someone else did make a change to include a commented out line to include therubyracter in the Gemfile at all times, with no explanation of what the commented out line is. I don't think that this provides any value whatsoever.