What is webruby?
- Ruby implementation that runs in the browser
- Based on mruby
- Calling JavaScript directly from Ruby
mruby
- Matz's embeddable minimal implementation of Ruby language
- Written in C99
- Minimal, Embeddable, Modular, Configurable
- Targeting Mobile device/Robots/Digital appliances/Games
What about the Web?
emscripten
- LLVM-to-JavaScript compiler
- Generated JS code runs very fast, and gets faster every day
-
asm.js: subset of JavaScript used as low-level, efficient compiler target
Loading mode
run()
load bytecode packed in generated JS file
run_bytecode(bytecode)
load bytecode
run_source(src)
parse and load Ruby source code on-the-fly
If we do not need run_source(src), we may be able to get rid of all the parsing code!
Load source on-the-fly
$(document).ready(function() {
var src = "5.times { puts 'Ruby is awesome!' }";
var w = WEBRUBY();
w.run_source(src);
w.close();
});
mruby test cases
Actually it may not be that slow because of JIT!
Okay, I can run Ruby in the browser.
But how can I access DOM/my fancy JavaScript library?
mruby-js
- Grouped as a mruby gem
- DOM access
- Type conversion between Ruby and JavaScript
- JavaScript method invoking
- Callback handling(JavaScript functions and Ruby procs)
Example to use
# gets window object
window = MrubyJs.window
# gets jQuery selected object, this is a function call!
# you can also use jQuery.invoke("#container")
container = window.jQuery["#container"]
# appends new tag
# another way of writing this: container.append["content"]
container.append("<p>This is inserted using run_source()!</p>")
Demo
DOM access
DOM is a tree!
Type conversion
Ruby type
Direction
JavaScript type
42
←→
42
3.14
←→
3.14
true
←→
true
nil
←→
undefined
"String"
←→
"String"
:symbol
→
"symbol"
Proc.new { ... }
→
function() { ... }
[ ... ]
→
[ ... ]
{ ... }
→
{ ... }
Wrap using instance_eval
MrubyJs.window.instance_eval do
if confirm("continue?")
console.log "you chose continue"
food = prompt("What's your favourite food?")
alert "Really?? #{food}?\nThat's gross."
jQuery('body').prepend("<h1>Likes #{food}</h1>")
else
console.log "you chose not to coninue"
end
end
mruby-js limitations
JavaScript
Ruby
foo.bar()
foo.bar.invoke or foo.bar[]
new bar("foo")
bar.invoke_new("foo")
var a = bar; a(2);
a = window.bar; a[2]
When should I use webruby?
Drawbacks
- Giant webruby.js file
Version
Raw
gzip -1
non-asm.js
3.2M
691K
asm.js
2.2M
661K
- Slow startup time
- Double GC(maybe asm.js can help with this?)
Places webruby might fit
-
Cross-platform games
- Common game logic in Ruby
- Web, iOS, Android, PlayStation...
- OpenGL ES 2 as rendering API
-
Web apps
- Business logic in Ruby
- Interactions with jQuery, three.js, Backbone.js, Meteor...