DEV Community

Cover image for Ruby on the Frontend? Choose Your Weapon
Jared White
Jared White

Posted on • Originally published at

Ruby on the Frontend? Choose Your Weapon

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.


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!"
Enter fullscreen mode Exit fullscreen mode

will get converted to:

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

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

  • Depending on how you configure Ruby2JS, you can convert classes to old-school JS functions/constructors, or you can use modern ES6+ classes like in the example here (which I recommend).
  • Ruby2JS provides “filters” which you can apply selectively to your code to enable new functionality. In this example, the camelCase filter automatically converts typical Ruby snake_case to camelCase as is common in Javascript. The functions filter automatically converts many popular Ruby methods into JS counterparts (so upcase becomes toUpperCase). And the return filter automatically add a return to the end of a method just like how Ruby works.
  • String interpolation in Ruby magically become valid ES6+ string interpolation, and it even works with squiggly heredocs!

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!


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 =, $nesting = [], nil = Opal.nil, $$$ = Opal.const_get_qualified, $$ = Opal.const_get_relative, $breaker = Opal.breaker, $slice = Opal.slice, $klass = Opal.klass;

  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)
Enter fullscreen mode Exit fullscreen mode

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.


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

  • If you use Webpack and already have a lot of JS code or libraries you need to interoperate with, Ruby2JS is a capable and lightweight solution which integrates easily into your build pipeline.
  • If you’re starting from scratch and want all the power of a full Ruby runtime as well as opportunities to write isomorphic Ruby code, Opal might be just what the doctor ordered.

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.

Want to receive a timely tip you can apply directly to your Ruby site or application each week? Subscribe to today to => hashrocket into the future and become a wiz at this delightful and powerful language.

Discussion (2)

nfilzi profile image
Nicolas Filzi

Thanks for sharing 🙏
Any takes on

jaredcwhite profile image
Jared White Author

Conceptually, I think it looks really cool! As a matter of personal preference, I tend to shy away from abstractions around HTML markup. Also I'm not sold on the idea of using Vue for reactive interfaces any more than I'm onboard React, or Svelte, or (insert non-web-components-based framework here). But it does seem very well thought out.