Out Now JavaScript for Rails Developers

JavaScript for Rails Developers is Coming Soon

It is out now! Get your copy now


Late last year I sat down and looked at some of this site’s stats. I had loads of articles written that are read by people in the 5-digits every month. Next to that I have a sizeable following on dev.to (+30k) and a solid amount of email subscribers. From all the articles I write, the ones on JavaScript elicit the most questions: “what if I want to do this?”, “how would you fix that?” and so on.

So, after talking about it with a few developer-friends, I pre-announced a book: “JavaScript for Rails Developers”. It was not a completely new idea, I had it jotted down in my ideas-list for a few years already, but now I had a theme of sorts as well: to make JavaScript your second-favorite language. I had a hunch it was something the market was interested in, but I wasn’t 100% sure.

So I created a page with a promise of the book and the option to pre-order it with a big discount. Since then a good number of you pre-ordered the book. So much so, that I was confident this book should become reality (I set a goal for myself, and if not reached, I would refund all).

So after I decided to go through with the book I spent too much time on finding the right approach. Writing a book is far from the tightly-scoped articles I write here. But at the same, the hands-on articles; building something tangible, always performed better than the more abstract ones.

So after many false starts (no really: many!), I finally settled on an idea: building a code editor in Stimulus, based on CodeMirror. This might seem superficial, but I set it up to start with the very basics: using a third-party dependency in Stimulus to extending the functionality with each chapter. Then I dive deeper whenever something new is introduced.

Here is an excerpt (the actual markdown/asciidoc I am writing):

(…)

Now you got a super basic editor working that is not much better than running data:text/html, <html contenteditable> in your browser. The content on load is static and any change made is lost when you refresh the page.

3.3.1 Passing data to a Stimulus controller

Stimulus has the values API that allows to pass data to the controller from the HTML. Like a lot of things in Rails, Stimulus also follows certain conventions. You can pass values, like strings, integers and hash and array-objects using the following syntax: data-[controllerName]-[valueName]-value="".

Then in the controller you define it using the static values object, like this:

import { Controller } from "@hotwired/stimulus"
import { basicSetup } from "codemirror"
import { EditorView } from "@codemirror/view"

export default class extends Controller {
  static values = { content: String }

  // …
}

Static class field in JavaScript

Wait… “static values object”? You can compare the static class field to Ruby’s class methods (self. or ⁠class << self). It defines methods that belong to the class itself rather than instances of the class.

In Ruby:

class Example
  def self.class_method
    "It me!"
  end
end

Example.class_method # => "It me!"

In JavaScript:

class Example {
  static classMethod() {
    return "It me!"
  }
}

Example.classMethod() // "It me!"

Both look pretty much alike, right? As an aside: in a later chapter, I will dive deeper into JavaScript classes.

Stimulus adds some extras to it too; “hey, these properties should be available across all instances of this controller (not just the current instance). Oh… also I want you to automatically create methods to get/set these values.”

So with the above added static values = {} line, you automatically get:

  1. Getters, like ⁠this.contenValue;
  2. Setters, like ⁠this.contenValue = 42;
  3. Has-methods, like ⁠this.hasContentVale.

(…)

Fat-arrow functions

But before continuing, there is some interesting, and often confusing, JavaScript tomfoolery going on here that trips up many Ruby developers:

EditorView.updateListener.of((update) => {
  // …
})

What you see here is called a (fat) arrow function () => {}. It was introduced in ES6/ES2015. In Ruby you can compare it to the ⁠-> (lambda) syntax, but with the added benefit of a lexical this binding. Lexical-what? It will automatically keep this pointing to where it was defined. Before ES6/ES2015, you had to add bind(this). Let’s change the above code to use the post-ES6 syntax to check it out:

// …
connect() {
  this.editor = new EditorView({
    doc: this.contentValue,
    parent: this.element,
    extensions: [
        basicSetup,
        // EditorView.updateListener.of((update) => {
            // if (update.docChanged) { this.#update() }
        // })
        EditorView.updateListener.of(function(update) {
          if (update.docChanged) { this.#update() }
        }.bind(this))
        ]
    })
    }
// …

When making changes in the editor you will still notice the console output with Update logs. Let’s now remove bind(this) and try updating the editor’s content again.

  // …
  connect() {
    this.editor = new EditorView({
      doc: this.contentValue,
      parent: this.element,
      extensions: [
        basicSetup,
        // EditorView.updateListener.of((update) => {
            // if (update.docChanged) { this.#update() }
        // })
        EditorView.updateListener.of(function(update) {
          if (update.docChanged) { this.#update() }
        })
      ]
    })
  }
// …

Errors! If you use a modern editor, you might already see a warning: #update is declared but its value is never read.

Without using bind(this) or the (fat) arrow function, this would be the CodeMirror editor’s context/scope because that is what is calling the function. So this.#update fails: CodeMirror doesn’t have an #update method, only the editor_controller does. Compared to Ruby it is akin to losing the self reference inside a block.

(…)

It has the hands-on approach of building something real and useful, while learning (new, modern) JavaScript step by step. I find this works much better than going over JavaScript concepts in the abstract.

I am currently editing the book. Fixing typo’s, removing parts and improving bits. While I have never been so unsure about something I have created (ie. what will you think), I am also really happy with how the book turned out.

Pricing

The tentative pricing looks like this:

  1. Solo Developer ($39) — full Book (PDF/ePub); full code-base access; code snippets
  2. Professional ($69) — everything in Solo Developer; markdown Editor + Preview Variant; railsdesigners.com community access (launching summer 2025; $49 value!)
  3. Team ($169) — everything in Professional; share with 5 developers; 5 community seats

If you have been a Rails developer who has cursed at JavaScript, this book might be for you. If you’ve been a Rails developer avoiding JavaScript at all costs, this book is what you need. For Rails developers who’ve wished JavaScript would just disappear, this book might change your mind.

Publishing date for JavaScript for Rails Developers is scheduled for April 2025 (yep, still leaves room for interpretation as there are a few tech hurdles to take still). If you want to get notified when you can get your hands on it, subscribe to the newsletter (I might sent a discount code when launching. Who knows!).

Check out JavaScript for Rails Developers.

Published at . Have suggestions or improvements on this content? Do reach out.

Join Rails developers getting deep dives on modern front-end patterns—from Hotwire, Tailwind CSS and ViewComponent. Fresh insights from Rails Designer HQ.
JavaScript for Rails Developers
Out now

UI components Library for Ruby on Rails apps

$ 149 one-time
payment

View components
  • One-time Payment

  • Access to the Entire Library

  • Built using ViewComponent

  • Designed with Tailwind CSS

  • Enhanced with Hotwire