DEV Community

Tomasz Wegrzanowski
Tomasz Wegrzanowski

Posted on

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.

Discussion (0)