Bridgetown2026-03-16T17:09:25-04:00https://www.ruby2js.com/feed.xmlRuby2JSRuby2JS is an extensible Ruby to modern JavaScript transpiler you can use in production today.The Ruby2JS Story: A Decade of Transpilation2025-12-14T00:00:00-05:002025-12-14T00:00:00-05:00repo://posts.collection/_posts/2025-12-14-ruby2js-story.md<p>Ruby2JS began in October 2013, forked from Marcos Castoria’s original <code class="highlighter-rouge">maca/Ruby2JS</code> project. The timing was notable: JavaScript was still in its ES5 era. Classes required prototype chain manipulation. Modules didn’t exist—you used AMD, CommonJS, or globals. Destructuring? Arrow functions? Forget it.</p> <p>The appeal of transpiling Ruby to JavaScript was straightforward: write elegant Ruby syntax and generate the verbose JavaScript that browsers understood.</p> <h2 id="the-early-years-2013-2019">The Early Years (2013-2019)</h2> <p>Development was intense in the beginning—159 commits in just the final two months of 2013. The codebase grew steadily:</p> <table> <thead> <tr> <th>Year</th> <th>Commits</th> <th>Notes</th> </tr> </thead> <tbody> <tr> <td>2013</td> <td>159</td> <td>Project launch</td> </tr> <tr> <td>2014</td> <td>96</td> <td>Steady growth</td> </tr> <tr> <td>2015</td> <td>161</td> <td>React filter added</td> </tr> <tr> <td>2016</td> <td>11</td> <td>Activity slowdown</td> </tr> <tr> <td>2017</td> <td>116</td> <td>Recovery</td> </tr> <tr> <td>2018</td> <td>177</td> <td>ES2015 support finally added</td> </tr> <tr> <td>2019</td> <td>57</td> <td>Tapering off</td> </tr> </tbody> </table> <p>The irony wasn’t lost on anyone: ES2015 (ES6) shipped in June 2015, but Ruby2JS didn’t add ES2015 class support until December 2017—over two years later. By then, JavaScript had native classes, modules, arrow functions, template literals, destructuring, and spread operators. The gap that Ruby2JS originally filled was closing.</p> <h2 id="jared-white-enters-october-2020">Jared White Enters (October 2020)</h2> <p>In October 2020, Jared White arrived and reinvigorated the project. His first commits landed on October 6, 2020, focused on tagged template literals and camelCase filter improvements.</p> <p>What followed was remarkable. In just over a year, Jared:</p> <ul> <li>Built the <strong>ruby2js.com website</strong> using Bridgetown (launched December 2020)</li> <li>Drove <strong>version 4.0.0</strong> (February 2021) with major modernizations</li> <li>Added the <strong>Stimulus filter</strong> for Hotwire integration</li> <li>Created <strong>LitElement support</strong></li> <li>Expanded the <strong>preset system</strong> for easier configuration</li> <li>Released <strong>version 5.0.0</strong> (May 2022)</li> </ul> <p>The numbers tell the story. The project hit its peak activity with 451 commits in 2021—more than any previous year. Jared contributed 199 commits total, second only to my 1,615.</p> <p>Jared brought something the project desperately needed: energy, vision, and a focus on modern web development patterns. The Bridgetown documentation site he built made Ruby2JS accessible to a whole new generation of developers.</p> <h2 id="the-quiet-period-2022-2024">The Quiet Period (2022-2024)</h2> <p>After version 5.0.0, activity gradually slowed:</p> <table> <thead> <tr> <th>Year</th> <th>Commits</th> </tr> </thead> <tbody> <tr> <td>2022</td> <td>65</td> </tr> <tr> <td>2023</td> <td>21</td> </tr> <tr> <td>2024</td> <td>7</td> </tr> </tbody> </table> <p>By May 2024, version 5.1.2 shipped—the last release before a long pause. Opal remained stuck at version 1.1.1 due to a compilation issue that was never fully resolved. Bridgetown sat at 1.3.4. The live demos on ruby2js.com stopped working.</p> <p>On January 23, 2025, Jared formally <a href="https://github.com/ruby2js/ruby2js/discussions/227">announced his departure</a>, acknowledging that “there are a number of PRs and issues stacking up” but explaining that his time was consumed by other open source projects, particularly Bridgetown itself. He graciously noted that he hadn’t created the project and hadn’t written most of the codebase—leaving the door open for renewed stewardship.</p> <h2 id="coming-home-november-2025">Coming Home (November 2025)</h2> <p>My return was prompted by a practical need: <a href="https://intertwingly.net/blog/2025/11/25/ERB-Stimulus-Offline.html">offline functionality for a Rails application</a>. I found the project with 21 open issues and 7 pending pull requests. The demos were broken. Dependencies were years out of date.</p> <p>Since November 27, 2025, there have been over 360 commits, <strong>30 issues closed</strong>, and <strong>44 pull requests merged</strong>.</p> <p><strong>Infrastructure modernization:</strong></p> <ul> <li>Opal upgraded from 1.1.1 to 1.8</li> <li>Bridgetown upgraded from 1.3.4 to 2.0.5</li> <li>Pre-ES2020 support retired (ES2015-ES2019 removed)</li> <li>Prism parser support for Ruby 3.4+</li> </ul> <p><strong>The self-hosting breakthrough:</strong></p> <ul> <li>Ruby2JS now transpiles <em>itself</em> to JavaScript</li> <li>A unified 200KB <code class="highlighter-rouge">ruby2js.mjs</code> bundle (no Ruby required)</li> <li>245 tests passing against the JavaScript implementation</li> <li>Enables true dual-target development—same Ruby source running on server and browser</li> </ul> <p><strong>New framework filters:</strong></p> <ul> <li><strong>ERB</strong> and <strong>HAML</strong> template support</li> <li><strong>Turbo</strong> for custom Turbo Stream actions</li> <li><strong>Alpine.js</strong> component registration</li> <li><strong>ActionCable</strong> WebSocket DSL</li> <li><strong>Jest</strong> for RSpec-style testing syntax</li> <li><strong>Stimulus</strong> enhanced with outlets support (3.x)</li> </ul> <p><strong>Enhanced Ruby patterns:</strong></p> <ul> <li>Type introspection (<code class="highlighter-rouge">is_a?</code>, <code class="highlighter-rouge">instance_of?</code>, <code class="highlighter-rouge">respond_to?</code>)</li> <li>Class introspection (<code class="highlighter-rouge">obj.class</code>, <code class="highlighter-rouge">obj.class.name</code>, <code class="highlighter-rouge">superclass</code>)</li> <li>Module mixins (<code class="highlighter-rouge">include</code>, <code class="highlighter-rouge">extend</code>)</li> </ul> <p><strong>New documentation:</strong></p> <ul> <li>Complete User’s Guide for dual-target development</li> <li>Patterns, pragmas, and anti-patterns documentation</li> <li>Live demos throughout</li> </ul> <p>The self-hosting work was particularly significant—proving that Ruby2JS can handle substantial, real-world Ruby code by successfully converting its own 60+ converter handlers and serializer to JavaScript.</p> <h2 id="the-numbers">The Numbers</h2> <p>After 11 years:</p> <ul> <li><strong>1,901 total commits</strong></li> <li><strong>19 releases</strong> (v3.6.0 through v5.1.2, with an upcoming 6.0 beta)</li> <li><strong>~60 AST node handlers</strong></li> <li><strong>~23 filters</strong> (functions, esm, camelCase, react, stimulus, and more)</li> </ul> <h2 id="thank-you-jared">Thank You, Jared</h2> <p>Jared White kept Ruby2JS alive and relevant during a critical period. His documentation work, his filters, his energy—they transformed a useful but aging tool into something modern developers could actually adopt. The project is better for his stewardship, and I’m grateful he held the torch when I couldn’t.</p> <p>Open source thrives on these handoffs. Sometimes you carry the load, sometimes you pass it on, and sometimes—years later—you pick it back up again.</p>Sam RubyRuby2JS 5.1, esbuild, and a Peek at the Future2023-02-20T00:00:00-05:002023-02-20T00:00:00-05:00repo://posts.collection/_posts/2023-02-20-future-of-ruby2js.md<p>At long last, <strong>Ruby2JS 5.1 is here!</strong> It comes packed with several very welcome features:</p> <ul> <li>A brand-new Ruby-based configuration DSL</li> <li>A “preset” option for sane defaults</li> <li>Magic comment support for sharing portable Ruby2JS code (based on the preset)</li> </ul> <p>In addition, the <a href="https://github.com/ruby2js/ruby2js/tree/master/packages/esbuild-plugin">esbuild plugin</a> has reached 1.0 status and has been re-architected to use the Ruby version of the compiler rather than the Node (aka Opal) version. Why? Performance and modern language compatibility.</p> <p>Let’s dig in a bit on all these new features! And keep reading as well for an update on the status of Ruby2JS and its open source governance.</p> <h2 id="ruby-based-configuration">Ruby-based Configuration</h2> <p>Ruby2JS, despite being a language transpiler usually needing some degree of configuration, never had a canonical format for project-based configuration. Until today!</p> <p>You can add <code class="highlighter-rouge">config/ruby2js.rb</code> to your project and both the Ruby API and the CLI tool will automatically detect its presence and use it for configuration. In addition, you can specify the location of a configuration file manually if you prefer to use a different filename or folder.</p> <p>The configuration format is very simple and easy to work with, just like other configuration formats such as Puma. You can read all about it in <a href="/docs/options">the documentation here</a>. But that’s not all!</p> <h2 id="a-preset-configuration-for-sane-defaults">A Preset Configuration for Sane Defaults</h2> <p>We believe most Ruby2JS code would benefit greatly from transpiling to a modern ECMAScript version (namely ES2021), using a few common filters such as <a href="/docs/filters/functions">Functions</a>, <a href="/docs/filters/esm">ESM</a>, and <a href="/docs/filters/return">Return</a>, using identity-based comparison operators (aka <code class="highlighter-rouge">==</code> becomes <code class="highlighter-rouge">===</code>), and automatically underscoring instance variables (<code class="highlighter-rouge">@x</code> becomes <code class="highlighter-rouge">this._x</code>).</p> <p>So that’s exactly what we built. By simply adding <code class="highlighter-rouge">preset</code> to a configuration file or passing <code class="highlighter-rouge">preset: true</code> or <code class="highlighter-rouge">--preset</code> to the Ruby API or CLI respectively, you can gain all the benefits of these common options. In addition, by writing your code to use the preset, you can ensure wider compatibility between projects and between tutorials/code samples and production workflows.</p> <p>Even more to that point, we’ve introduced the idea of a “magic comment”. By adding <code class="highlighter-rouge"># ruby2js: preset</code> to the top of a <code class="highlighter-rouge">.js.rb</code> file, you instruct Ruby2JS to use the preset configuration for that file. You can even add additional filters right in the magic comment, change the ES level, or disable a filter that comes with the preset. <a href="/docs/options">Read the documentation here.</a></p> <p>We believe all of these features now mean that Ruby2JS code is easier to teach and easier to share. We took your feedback about these issues in the past to heart and are trying to make improvements for better DX.</p> <h2 id="esbuild-is-faster-using-ruby">esbuild is faster using Ruby?!</h2> <p><a href="https://esbuild.github.io">esbuild</a> is a modern, fast, and easily-configured frontend bundling tool, and we want to support it as a “first-party” citizen in the Ruby2JS ecosystem.</p> <p>esbuild is fast because its core code is written in Go, not JavaScript. Along similar lines, we discovered something extraordinary when testing the beta of the esbuild bundling package. When we tried spawning a process to transpile a file using the Ruby version of Ruby2JS, rather than the Opal/Node-powered JavaScript version, we discovered that it was actually faster! And not just a little bit faster…<a href="https://github.com/ruby2js/ruby2js/discussions/170">almost 2x faster!</a></p> <p>Transpiling using the Ruby version also has the added benefit that the syntax of the code you write on the frontend matches the version of Ruby your project uses overall. Before, you could be using Ruby 3.2 in your overall stack but the “version of Ruby” (in fact the version of Opal) might be older. In fact, there’s actually an outstanding issue that the version of Opal used to generate the JavaScript version of Ruby2JS is locked to an older version of Opal due to bugs introduced when upgrading. More on that below…</p> <p>So, all in all, it makes sense to standardize around Ruby, even when using esbuild. After all, I would be shocked if anyone had an interest in writing Ruby2JS frontend code and using esbuild as a bundling tool who <em>didn’t</em> actually have Ruby installed for use in a Ruby-based web project. So why rely on Opal/Node if we don’t have to?</p> <h2 id="the-future-of-ruby2js">The Future of Ruby2JS</h2> <p>Which brings us to a broader topic: the future of this project.</p> <p><a href="http://intertwingly.net/blog/">Sam Ruby</a>, a well-known figure in the Ruby community and the brains behind Ruby2JS for many years, stepped down as an active maintainer in 2021. This effectively left me as the sole maintainer of Ruby2JS—and not only the sole maintainer, but by and large the <em>only</em> active contributor to Ruby2JS.</p> <p>I had started contributing to the project in 2020, and through much trial-and-error and helpful mentorship from Sam, I eventually learned my way around the codebase enough to help usher in a few improvements to the feature set as well as set up this Bridgetown documentation site. It was an amazing experience, and I’d like to thank Sam publicly for his trust in (and patience with!) me.</p> <p><strong>Here’s the deal:</strong> I love this project and sincerely hope to continue to see it fill an important role in the niche of “Ruby frontend web developers” as <a href="https://www.fullstackruby.dev">I like to consider myself to be</a>.</p> <p>But the fact of the matter is I have my hands very full with the <a href="https://www.bridgetownrb.com">Bridgetown project</a>, and my ability to devote much attention to Ruby2JS is limited. In addition, what attention I <em>can</em> devote to Ruby2JS is mostly relegated to the use cases for which Ruby2JS is personally useful to me. I’m not saying that’s ideal. It just is what it is.</p> <p>So because I <em>primarily</em> use Ruby2JS for writing web components (usually using <a href="https://lit.dev">Lit</a>) and bundling using esbuild, that is the principal scope I intend to maintain going forward. I would also argue that it’s a very ergonomic and obvious way to make the most of Ruby2JS as a web developer building projects (as I do) with Rails or Bridgetown.</p> <p>Thus I have decided to deprecate quite a number of features (“filters” and other integration points) which will be removed officially by the time Ruby2JS 6.0 is released. I don’t have any immediate release date for that, but for the sake of discussion let’s assume it will happen towards the end of this year.</p> <p>The list of deprecated features is as follows:</p> <ul> <li>jQuery filter</li> <li>JSX filter</li> <li>matchAll filter (only necessary for ES &lt; 2020)</li> <li>minitest-jasmine filter</li> <li>Preact filter</li> <li>React filter</li> <li>Require filter</li> <li>Underscore filter</li> <li>Vue filter</li> <li>CGI server integration</li> <li>ExecJS integration</li> <li>Haml integration</li> <li>Rails integration (outside of the new “jsbundling” esbuild pipeline)</li> <li>Sinatra integration (as a view template type)</li> <li>Sprockets integration</li> <li>“use strict” option (all modern ESM code is considered strict anyway)</li> <li>Webpack loader</li> </ul> <p>In addition, I am actively looking for a maintainer to own the <a href="https://github.com/ruby2js/ruby2js/tree/master/packages">Rollup and Vite plugins</a> for transpiling Ruby2JS code via those bundlers. I don’t myself use Rollup/Vite, but I understand they’re quite popular as an alternative to using esbuild directly. They still need to be upgraded to use Ruby rather than Node for the transpilation (like esbuild).</p> <p>If any of these stand out to you as having a <em>serious impact</em> on current production workflows, let’s talk about possible strategies—either migrations to a better solution, or extracting features out to their own repo. For example, I simply have no interest in maintaining a React filter. I don’t recommend people adopt React in new projects as a general rule, and if they do, then I recommend they use the Next.js framework because it just makes React much, much better. React + Ruby2JS is not a solution I can, in all good conscience, promote.</p> <p><strong>However</strong>, if someone <em>really</em> needs a React filter long into the future for their projects, I’d be happy to help extract this functionality out to a separate gem with fresh open source governance. Again, that holds true for any of the deprecated features listed above.</p> <p>The alternative to this approach, <em>and one I strongly considered</em>, would be for me to step down myself as a maintainer of Ruby2JS and seek someone else in the community to come onboard instead. I decided against this move for several reasons:</p> <ul> <li>I still really enjoy writing Ruby2JS code and singing the praises of the project.</li> <li>This is a pretty gnarly codebase to wrap your head around, and I had the benefit of being mentored by Sam Ruby himself. For someone to come in fresh and begin to make sizable contributions, that’s a tall order—especially with the variety of JS packages now in the project as well. There’s also a fair bit of technical debt that has no clear upgrade path at present. For example:</li> <li>We’re locked into an old version of Opal for compiling the JavaScript version of the Ruby2JS compiler. Over time, this will result in the Node version of Ruby2JS falling farther and farther behind relative to its native Ruby counterpart. It may mean that, at some future date, we sunset this other than for trivial use (such as the online interactive demos)—or we figure out why the transpiler is broken on newer version of Opal which will take a considerable amount of time (I’ve failed after two separate attempts).</li> <li>And as mentioned above, nobody else <em>has</em> been contributing with any frequency.</li> </ul> <p>So ultimately I gladly intend on continuing to act as lead maintainer for Ruby2JS—while significantly reducing the scope of the project down to what (in my opinion) it is best suited for and what I best understand. And beyond that, any additional features are quite welcome to be handled via Ruby2JS “plugins” by others in the community.</p> <h2 id="the-future-of-ruby-on-the-frontend">The Future of Ruby on the Frontend</h2> <p>This brings me to my final and most general point regarding where we, the Ruby web developer community, are headed.</p> <p>I have become fairly convinced with the release of <a href="https://ruby.github.io/ruby.wasm/">Ruby 3.2 and its brand-new WebAssembly support</a> that <strong>the future of Ruby on the frontend is Wasm</strong>. This means <a href="https://www.fullstackruby.dev/podcast/7/">I forsee a day</a> when writing <em>actual Ruby code</em> and directly executing it in the browser will be feasible for a considerable number of ambitious projects.</p> <p>In effect, this will render both Ruby2JS <em>and</em> Opal obsolete. Why try to fiddle with various compile-to-JavaScript languages and syntaxes when you can simply write <strong>Ruby</strong> and run it?! That’s obviously the ideal, even if today there are significant hurdles to overcome (most notably large Wasm payloads and simplistic Ruby&lt;-&gt;JS APIs).</p> <p>So I look forward to that day, even if it’s still a few years away. In the meantime, I’m thrilled I can continue to write frontend code in a Ruby-like way using Ruby2JS. And I hope you are as well.</p> <p><strong>Questions? Ideas? Suggestions?</strong> Hop in our <a href="https://github.com/ruby2js/ruby2js/discussions">GitHub Discussions</a> and let us know! And if you find an issue with Ruby2JS 5.1, please file an issue report so we can make Ruby2JS. Better yet, if you’d like to become a contributor yourself to Ruby2JS, we welcome your involvement and support!</p>Jared WhiteRegister2021-03-22T00:00:00-04:002021-03-22T00:00:00-04:00repo://posts.collection/_posts/2021-03-22-register.md<p>Originally, CoffeeScript had a <a href="https://coffeescript.org/#nodejs-usage">coffeescript/register</a> module, which would automatically compile CoffeeScript files on the fly.</p> <p>Originally, Babel later adopted it, producing the <a href="https://babeljs.io/docs/en/babel-register/">@babel/register</a> module, which will automatically compile <code class="highlighter-rouge">.es6</code>, <code class="highlighter-rouge">.es</code>, <code class="highlighter-rouge">.jsx</code>, <code class="highlighter-rouge">.mjs</code>, and <code class="highlighter-rouge">.js</code> files the fly.</p> <p>Now, Ruby2JS has adopted the idea, and in fact uses the <a href="https://github.com/ariporad/pirates#readme">same hook</a>, and makes available the <a href="https://www.npmjs.com/package/@ruby2js/register">@ruby2js/register</a> module, which will automatically compile <code class="highlighter-rouge">.rb</code> files on the fly.</p> <h2 id="demonstration">Demonstration</h2> <p>Let’s start with the simple and somewhat canonical greet function in Ruby:</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># greet.rb</span> <span class="k">def</span> <span class="nf">greet</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span> <span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">!"</span> <span class="k">end</span> </code></pre></div></div> <p>Now add a main program, in JavaScript, which registers and configures Ruby2JS, and then calls out to the above script:</p> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// main.js</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">@ruby2js/register</span><span class="dl">'</span><span class="p">)({</span> <span class="na">options</span><span class="p">:</span> <span class="p">{</span> <span class="na">eslevel</span><span class="p">:</span> <span class="mi">2021</span><span class="p">,</span> <span class="na">autoexports</span><span class="p">:</span> <span class="dl">'</span><span class="s1">default</span><span class="dl">'</span><span class="p">,</span> <span class="na">filters</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">cjs</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">functions</span><span class="dl">'</span><span class="p">]</span> <span class="p">}</span> <span class="p">})</span> <span class="kd">const</span> <span class="nx">greet</span> <span class="o">=</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./greet</span><span class="dl">'</span><span class="p">)</span> <span class="nf">greet</span><span class="p">(</span><span class="dl">'</span><span class="s1">World</span><span class="dl">'</span><span class="p">)</span> </code></pre></div></div> <p>All that’s left is to install the module and go:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yarn add @ruby2js/register node main.js </code></pre></div></div> <p>Enjoy!</p>Sam RubyNew Stimulus Design Pattern?2021-02-24T00:00:00-05:002021-02-24T00:00:00-05:00repo://posts.collection/_posts/2021-02-24-new-stimulus-design-pattern.md<p>As far as I know, this is a new design pattern for Stimulus. At the very least, it isn’t something I was able to readily find with Google searches.</p> <p>First, let’s gets some standard stuff out of the way. The <a href="https://ruby2js.com">Ruby2JS.com</a> is built using the <a href="https://www.bridgetownrb.com/">Bridgetown</a> static site generator. <a href="https://opalrb.com/">Opal</a> is used to generate the bulk of the scripts to be executed. <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching">HTTP caching</a> ensures that these scripts are only downloaded when they change. <a href="Turbo">Turbo</a> ensures that these scripts are only loaded once per site visit. <a href="Stimulus">Stimulus</a> associates HTML elements with controllers.</p> <p>All standard stuff so far.</p> <p><a href="https://ruby2js.com">Ruby2JS.com</a> has three controllers on the page. The first is a Ruby editor. The second is a read-only JavaScript view. And the third is invisible, but runs the JavaScript which outputs to the console log. Other pages have these same three controllers with different arrangements and/or different data, for example the <a href="https://www.ruby2js.com/examples/stimulus/">Stimulus introduction</a> and the <a href="https://www.ruby2js.com/examples/stimulus/">React Simple Component</a>. The <a href="https://www.ruby2js.com/demo">Ruby2JS Demo</a> has a Ruby editor and a JS ouput, but doesn’t have a results controller and adds an options controller.</p> <p>The source to the controllers can be found in <a href="https://github.com/ruby2js/ruby2js/tree/master/demo/controllers">GitHub</a>. Unsurprisingly given that these controllers support the Ruby2JS site, they are written in Ruby.</p> <p>But that’s not the unique design pattern part.</p> <p>Look at a Ruby editor on any of the pages mentioned. There isn’t really any <a href="https://stimulus.hotwire.dev/reference/actions">Actions</a>, <a href="https://stimulus.hotwire.dev/reference/targets">Targets</a>, <a href="https://stimulus.hotwire.dev/reference/values">Values</a>, or <a href="https://stimulus.hotwire.dev/reference/css-classes">CSS Classes</a> to speak of.</p> <p>Instead, updates made in the Ruby editor are sent to <em>other</em> controllers. A global overview of the design of these pages: the options controller on the demo page will update the Ruby controller. The Ruby controller will update both the JavaScript and evaluation results controllers. And there is even a case where the evaluation results controller will update the Ruby controller, but we will get to that in a minute.</p> <p>All of this is accomplished by subclassing a <a href="https://github.com/ruby2js/ruby2js/blob/master/demo/livedemo.js.rb">common base class</a> and overridding the <code class="highlighter-rouge">source</code> method with calls to a <code class="highlighter-rouge">findController</code> method. The <code class="highlighter-rouge">findController</code> method unsurprisingly searches the <code class="highlighter-rouge">application.controllers</code> array. This base class also takes care of connecting sources with targets indpendent of the order in which the controllers connect.</p> <p>Once a source is paired with potentially multiple targets, messages pass via standard method calls and/or attribute accessors (getters and setters in JavaScript terms).</p> <p>As an example, <a href="https://github.com/ruby2js/ruby2js/blob/master/demo/controllers/ruby_controller.js.rb#L96">here</a> are the lines of code where <code class="highlighter-rouge">Ruby2JS.convert</code> is called and the resulting JavaScript is sent to each target.</p> <p>The JSController’s <a href="https://github.com/ruby2js/ruby2js/blob/91f75c3b83026bb0027c6fb390dafdd15a6ab6a9/demo/controllers/js_controller.js.rb#L38">implementation of the <code class="highlighter-rouge">contents=</code> method</a> will dispatch the content to the jsEditor.</p> <p>The EvalController’s <a href="https://github.com/ruby2js/ruby2js/blob/master/demo/controllers/eval_controller.js.rb">implementation of the <code class="highlighter-rouge">contents=</code> method</a> will load the script into a <code class="highlighter-rouge">script</code> element and append it to the document.</p> <p>An interesting detail: if you bring up the <a href="https://www.ruby2js.com/examples/stimulus/">Stimulus Introduction</a> page and click on the JavaScript tab you will see different results in Safari than you would in see in Chrome, Firefox, or Microsoft Edge. Safari doesn’t yet support <a href="https://github.com/tc39/proposal-static-class-features">static public fields</a>, so an assignment statement after the class definition is used instead.</p> <p>The way this works is that the Ruby souce code is initially converted to JavaScript using the <a href="https://www.ruby2js.com/docs/eslevels#es2022-support">ES2022 option</a>, and the results are sent to the evaluation controller. The evaluation controller captures the syntax error and given that this occurred on the very first update it will update the <code class="highlighter-rouge">options</code> in the Ruby Controller, triggering another conversion, the results of which are sent to both the JS and Eval controllers.</p> <p>While this usage is quite different than the traditional application of Stimulus, the end result is comparable: a site consisting entirely of static HTML augmented with a small number of <code class="highlighter-rouge">data-</code> attributes that cause the controllers to activate.</p> <p>I’m quite curious if others have seen this usage of Stimulus before, if they find it useful, or have any suggestions.</p>Sam RubyNew live demo2021-01-19T00:00:00-05:002021-01-19T00:00:00-05:00repo://posts.collection/_posts/2021-01-19-new-live-demo.md<p>Check it out <a href="https://www.ruby2js.com/demo?preset=true">here</a>.</p> <p>Because the conversion from Ruby to JavaScript is fast and runs right in your browser, this demo will update the converted output keystroke-by-keystroke as you enter your code. Find and fix your syntax errors, select the right filters and options, and ensure the JavaScript to be generated is what you intend before you commit your code.</p> <p>Or just use it to learn idiomatic equivalents to common Ruby language patterns. Just be sure to select a modern <code class="highlighter-rouge">eslevel</code>, and liberally add filters, particularly filter <code class="highlighter-rouge">functions</code>.</p> <p>Under the covers, it is running the same <a href="https://github.com/ruby2js/ruby2js">ruby2js</a> code, just converted from Ruby to JavaScript using the excellent <a href="https://opalrb.com/">Opal</a> converter.</p> <p>See a conversion that either isn’t quite right or isn’t the best it can be? <a href="../../docs/community/#ways-to-contribute">Let us know</a>!</p> <p>Why Opal? Because it is the <a href="../../docs/choose-your-tool">right tool for this job</a>.</p> <p><br /></p> <p><a href="/docs" class="button is-primary is-info">Ready to Give Ruby2JS a Try?</a></p>Sam RubyReact filter documentation has landed!2021-01-06T00:00:00-05:002021-01-06T00:00:00-05:00repo://posts.collection/_posts/2021-01-06-react-filter-documentation-has-landed.md<p>While filters can do one-for-one transformations, they can also do much more. The <a href="/docs/filters/react">react</a> filter will, for example, do the following:</p> <ul> <li> <p>Support multiple syntaxes for HTML, including <a href="https://react.dev/learn/writing-markup-with-jsx">JSX</a> and direct calls to <a href="https://react.dev/reference/react/createElement">React.createElement</a>.</p> </li> <li> <p>Unifying all of the mechanisms to initialize, reference, and update state with assignments and references to instance variables.</p> </li> <li> <p>Automatically <a href="https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/function/bind">bind</a> all event handlers.</p> </li> <li> <p>Eliminate the need to create event handlers for <a href="https://react.dev/reference/react-dom/components#form-components">controlled components</a>.</p> </li> </ul> <p>See the <a href="/docs/filters/react">documentation</a> for more details and live examples.</p>Sam RubyWelcome to the New Ruby2JS Website2020-12-29T00:00:00-05:002020-12-29T00:00:00-05:00repo://posts.collection/_posts/2020-12-29-welcome-to-the-new-ruby2js-website.md<p>There’s only so much you can do with a README on GitHub and then it’s time for an upgrade. 😎</p> <p>So here it is! The brand new <strong>Ruby2JS</strong> documentation site. Now that we have a spiffy new home on the interwebs, we’ll be polishing up and adding additional documentation and examples, as well as posting news updates as features and improvements get added to the project.</p> <p>Many thanks to <a href="https://github.com/rubys">Sam Ruby</a> for giving me (Jared) so much runway to transition everything over to the new site (and a <a href="https://github.com/ruby2js">new org on GitHub!</a>). Lots more exciting news in store for 2021!</p> <p><br /></p> <p><a href="/docs" class="button is-primary is-info">Ready to Give Ruby2JS a Try?</a></p>Jared White