Wednesday, October 24, 2012

Clementine gem - ClojureScript on Rails Asset Pipeline

After about a year of silence, Clementine gem, https://github.com/yokolet/clementine, has been updated. The remarkable feature of this gem is to make ClojureScript available on Rails asset pipeline. Like CoffeeScript, ClojureScript code is compiled dynamically with this gem. Besides, the gem works on both CRuby and JRuby. I've blogged before, but those blog posts got really old. So, I'm going to update for the latest version.

For those of you don't know ClojureScript, I recommand the book, http://shop.oreilly.com/product/0636920025139.do, which is very good to understand what it is. Also, you'd better to visit https://github.com/clojure/clojurescript and http://clojurescriptone.com/ to get familiar with ClojureScript.

The first thing to be done is to create a Rails app.
rails new blog
Then, add Clementine in your Gemfile.
Well, since I use the same Rails app for both JRuby and CRuby, my Gemfile looks like this:
source 'https://rubygems.org'

gem 'rails', '3.2.8'

gem 'sqlite3', :platforms => :mri_19
gem 'activerecord-jdbcsqlite3-adapter', :platforms => :jruby
gem 'jruby-openssl', :platforms => :jruby

# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'

  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
  gem 'therubyracer', :platforms => :mri_19
  gem 'therubyrhino', :platforms => :jruby

  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

gem 'clementine', '0.0.3'
After adding Clementine in the Gemfile, run the commend:
bundle install
While installing Clementine, you'll see confusing message, "Installing clementine (version string) with native extensions." Clementine doesn't rely on C library at all. Clementine is just bootstrapping ClojureScript while installation is going on. Clementine has a whole ClojureScript code in it, but doesn't have Clojure and Google closure compiler/library that ClojureScript needs. Clementine runs ClojureScript's bootstrap command to grab those from each site during the installation. When the gem installation is completed, Clementine has an appropriate version of clojure.jar, compiler.jar, goog.jar and js.jar in its lib directory.

Next, create controller to see how ClojureScript works on Rails asset pipeine.
rails g controller Greetings index
As in "Using ClojureScript on a Web Page" sample at https://github.com/clojure/clojurescript/wiki/Quick-Start, create the file, app/assets/javascripts/hello.js.cljs and write:
(ns hello)
(defn ^:export greet [name]
  (str "Hellooooooooo " name))
Add three lines to app/views/greetings/index.html.erb, which looks like:
<script>
    alert(hello.greet("ClojureScript"));
</script>
<h1>Greetings#index</h1>
<p>Find me in app/views/greetings/index.html.erb</p>
That's it. Start Rails
rails s
and request http://localhost:3000/greetings/index from your browser. You'll see this javascript alert dialog
. If you tried on CRuby, you should have waited long time to see this dialog. This is because JVM got started to compile ClojureScript. Starting JVM is a huge job. I recommend JRuby to cut down the compilation time. JVM is already there.

The default setting is advanced optimization mode. So, you can see how it is compiled using browser's inspection feature:
If you want to see readable JavaScript code for debugging, you should specify options of ClojureScript. To give compiler options, create the file, config/initializers/clementine.rb and write Clementine options as in below:
Clementine.options[:optimizations] = :whitespace
Clementine.options[:pretty_print] = true
Don't forget to edit app/assets/javascripts/hello.js.cljs to see the effect of given options. If you don't change anything in hello.js.cljs, Rails won't call compiler. It is the asset pipeline.

Restart Rails and request the same URL. You'll see something like this on browser's inspection window:


That's all. Try ClojureScript on Rails.