DEV Community

Tomasz Wegrzanowski
Tomasz Wegrzanowski

Posted on

3 2

Electron Adventures: Episode 93: Opal Ruby

I tried it a few times before, and it was a bit too complicated, so I dropped it and did something else, but the series is nearing completion, so I can't postpone any longer.

Opal Ruby is complicated primarily because it's not meant to be used as JavaScript-like language, it's meant to be used as part of a bigger system, generally with a Ruby backend, so all that wiring is behind the scenes. But we'll use it directly.

For this episode, I'll only do the frontend (renderer) in Opal Ruby, and the backend (main) in JavaScript.

index.js

The backend process will just open public/index.html:

let { app, BrowserWindow } = require("electron")

function createWindow() {
  let win = new BrowserWindow({height: 600, width: 800})
  win.loadFile(`${__dirname}/public/index.html`)
}

app.on("ready", createWindow)

app.on("window-all-closed", () => {
  app.quit()
})
Enter fullscreen mode Exit fullscreen mode

public/index.html

For the app we'll just show a button, and a count of how many times it was clicked:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Ruby Opal Application</title>
    <link href="app.css" rel="stylesheet" type="text/css" />
  </head>
  <body>
    <button>Click the button</button>
    <div>Click count: <span id="count">0</span></div>
    <script src="./build/app.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

The compiled file will go to ./build/app.js.

public/app.css

We're doing basically mode: dark; display: center; except with a few more words:

body {
  margin: 0;
  background-color: #444;
  color: #fff;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  font-size: 300%;
  min-height: 100vh;
}

button {
  font-size: unset;
}
Enter fullscreen mode Exit fullscreen mode

Gemfile

That covers the Electron part, so let's get to the Ruby part. Gemfile is like package.json - and there's Gemfile.lock corresponding to package-lock.json

gem "opal", "~> 1.3"
Enter fullscreen mode Exit fullscreen mode

Rakefile

We need to tell Opal to build the app.js. There are likely some packages for watching the source folder and doing it automatically, but I decided to do it the hard way for now.

All this could also go into package.json scripts section.

require "pathname"

desc "Build JavaScript files"
task "build" do
  Pathname("public/build").mkpath
  sh "opal src/app.rb -c >public/build/app.js"
end
Enter fullscreen mode Exit fullscreen mode

src/app.rb

And finally the app! Opal Ruby generally requires wrappers around JavaScript objects. There are a few ways to do this - native module provides $$ which corresponds to JavaScript window/global except it wraps every JavaScript object in an Opal Ruby wrapper:

require "native"

counter = 0

button = $$.document.querySelector("button")
count = $$.document.querySelector("#count")

button.addEventListener("click") do
  counter += 1
  count.innerText = counter
end
Enter fullscreen mode Exit fullscreen mode

Results

Here's the results:

Episode 93 Screenshot

In the next episode we'll write the terminal app in Opal Ruby.

As usual, all the code for the episode is here.

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more