Ruby on the Frontend? Choose Your Weapon

Credit: Meritt Thomas on Unsplash

We all know that Ruby is a great language to use for the backend of your web application, but did you know you can write Ruby code for the frontend as well?

Not only that, but there are two available options to choose from when looking to “transpile” from Ruby to Javascript. These are:

Let’s take a quick peek at each one and see what might be right for your project.

Ruby2JS #

My personal favorite, Ruby2JS was created by Sam Ruby (yep, that’s his name), and it is intended to convert Ruby-like syntax to Javascript as cleanly and “natively” as possible. This means that (most of the time) you’ll get a line-by-line, 1:1 correlation between your source code and the JS output. For example:

class MyClass
  def my_method(str)
    ret = "Nice #{str} you got there!"
    ret.upcase()
  end
end

will get converted to:

class MyClass {
  myMethod(str) {
    let ret = `Nice ${str} you got there!`;
    return ret.toUpperCase()
  }
}

There’s actually a lot going on here so let me unpack it for you:

How do you get started using Ruby2JS? It’s pretty simple: if you’re using a framework with Webpack support (Rails, Bridgetown), you can add the rb2js-loader plugin along with the ruby2js gem, write some frontend files with a .js.rb extension, and import those right into your JS bundle. It even supports source maps right out of the box so if you have any errors, you can see the original Ruby source code right in your browser’s dev inspector!

Full disclosure: I recently joined the Ruby2JS team and built the Webpack loader, so let me know if you run into any issues and I’ll be glad to help!

Opal #

The Opal project was founded by Adam Beynon in 2012 with the ambitious goal of implementing a nearly-full-featured Ruby runtime in Javascript, and since then it has grown to support an amazing number of projects, frameworks, and use cases.

There are plenty of scenarios where you can take pretty sophisticated Ruby code, port it over to Opal as-is, and it just compiles and runs either via Node or in the browser which is pretty impressive.

Because Opal implements a Ruby runtime in Javascript, it adds many additional methods to native JS objects (strings, integers, etc.) using a $ prefix for use within Opal code. Classes are also implemented via primitives defined within Opal’s runtime layer. All this means that the final JS output can sometimes look a little closer to bytecode than traditional JS scripts.

For instance, the above example compiled via Opal would result in:

/* Generated by Opal 1.0.3 */
(function(Opal) {
  var self = Opal.top, $nesting = [], nil = Opal.nil, $$$ = Opal.const_get_qualified, $$ = Opal.const_get_relative, $breaker = Opal.breaker, $slice = Opal.slice, $klass = Opal.klass;

  Opal.add_stubs(['$upcase']);
  return (function($base, $super, $parent_nesting) {
    var self = $klass($base, $super, 'MyClass');

    var $nesting = [self].concat($parent_nesting), $MyClass_my_method$1;

    return (Opal.def(self, '$my_method', $MyClass_my_method$1 = function $$my_method(str) {
      var self = this, ret = nil;

      
      ret = "" + "Nice " + (str) + " you got there!";
      return ret.$upcase();
    }, $MyClass_my_method$1.$$arity = 1), nil) && 'my_method'
  })($nesting[0], null, $nesting)
})(Opal);

Thankfully, Opal too has support for source maps so you rarely need to look at anything like the above in day-to-day development—instead, your errors and debug output will reference clean Ruby source code in the dev inspector.

One of the more well-known frameworks using Opal is Hyperstack. Built on top of both Opal and React, Hyperstack lets you write “isomorphic” code that can run on both the server and the client, and you can reason about your web app using a well-defined component architecture and Ruby DSL.

Conclusion #

As you look at the requirements for your project, you can decide whether Ruby2JS or Opal might suit your needs.

Regardless of which you choose, it’s exciting to know that we can apply our Ruby knowledge to the frontend as well as the backend for web applications large and small. It’s a great day to be a Rubyist. small red gem symbolizing the Ruby language

Skip to content