Ruby - Write Once, Run Anywhere - Arrrrcamp 2014

Ruby - Write Once, Run Anywhere - Arrrrcamp 2014

Some people say that Ruby is dying.
I wouldn't…
I'd rather claim that Ruby is more alive than ever!
Few years ago we could only envy Javascript programmers while their favorite language was becoming ubiquitous. Currently, thanks to RubyMotion we can write desktop and mobile apps. While Opal can execute Ruby in a browser. With these tools we can finally write cross-platform Ruby apps.
Learn how!


Michał Taszycki

October 03, 2014


  1. Ruby - Write Once, Run Anywhere Michal Taszycki (GunpowderLabs)

  2. Who wants to play a game?

  3. Who wants to play a game?

  4. 2 Facts about Multiplayer Games • Players expect snappy interface

    • Players cheat
  5. What does it mean? • Game logic required in each

    client • Game logic required on server
  6. It used to mean A lot of redundancy

  7. But now… We have the technology!

  8. Opal.rb

  9. Opal.rb • Ruby to Javascript compiler • Performant • Version

    < 1.0, actively developed • Out of the box Rails integration • Interesting libraries start to show up
  10. RubyMotion

  11. RubyMotion • Compiles Ruby to ObjectiveC runtime • Android Support

    available in beta • Native performance • Version > 2.0, actively developed • Widely used in production
  12. mruby

  13. mruby • Supports ISO ruby standard • Can be embedded

    into any C application • low memory footprint • Faster than MRI • Works even on Arduino DUE (requires 96KB SRAM) • Promising for Windows desktop applications
  14. Is any of them really a Ruby == ? ==

    ? == ?
  15. Differences • No require at runtime • No eval at

    runtime • Methods can have incompatible names • Threads are working • Memory leaks possible
  16. Differences • no require at runtime • strings are immutable

    • symbols are strings • regexps differ • All numbers are floats • no for loop yet ;)
  17. Differences • no require at runtime • gems (mrgems) need

    to be compiled into mruby • no Bignumber support • Regular Expressions unavailable by default • optimized for size (but ofter faster than MRI)
  18. Is any of them really a Ruby

  19. They’re Ruby enough!

  20. Cross Platform Ruby

  21. Cross Platform Ruby

  22. Interactions

  23. Internal interactions Hexagonal Clean Architecture DCI DDD CQRS Cowboy Coding

    Functional Programming Micro Libraries
  24. This is your dreamland! Internal interactions DCI Hexagonal Clean Architecture

    DCI DDD Cowboy Coding Functional Programming CQRS Micro Libraries
  25. Interactions

  26. Access From Outside title_label.text = translator.get(:title) <h1><%= translator.get(:title) %></h1>

  27. Access From Outside event_logger.save_event(:user_signed_up) event_logger.save_event(:user_tapped_on_top_left_button) event_logger.save_event(:user_bought_an_in_app_purchase, type: "coin", amount: 1000)

    event_logger.save_event(:user_signed_in) event_logger.save_event(:user_browsed_products) event_logger.save_event(:user_bought_product, name: "beef_jerky", amount: 35)
  28. Interactions

  29. Driving from inside # toggle panels - same interface #

    for animation on all platforms ! image_editor_controller.animate_view( brushes_panel, :horizontall_slide, from: 0, to: -90) ! image_editor_controller.animate_view( shapes_panel, :horizontall_slide, from: -90, to: 0)
  30. Interactions

  31. class TodoItem def mark_as_done self.done = true end end Async

  32. ! ! ! # We want to save it afterwards

    on each platform todo.mark_as_done Async interactions
  33. Async interactions Abstract interface Notifications Aspect Oriented Programming

  34. class Todo def self.saver=(saver) @saver = saver end ! def

    mark_as_done self.done = true end end Abstract interface
  35. Abstract interface Todo.saver = todo.mark_as_done ! # or !

    Todo.saver = todo.mark_as_done
  36. Abstract interface +Well defined interaction - Core needs to know

    about use cases +Useful when use cases on each platform are similar
  37. Notifications class Todo include Eventable def mark_as_done self.done = true

    trigger(:marked_as_done, self) end end
  38. Notifications todo.on(:marked_as_done) do |todo| save_to_database(todo) end todo.mark_as_done ! # or

    ! todo.on(:marked_as_done) do |todo| post_to_api(todo) end todo.mark_as_done
  39. Notifications +Core doesn’t need to know use cases - Hard

    to compose interactions !Beware of memory leaks +Useful when use cases on each platform are a bit different
  40. AOP class Todo def mark_as_done self.done = true end end

  41. AOP class DatabaseTodoSaver include AspectOrientedLibraryOfChoice after Todo, :mark_as_done do |todo|

    save_to_database(todo) end end
  42. AOP class RestTodoSaver include AspectOrientedLibraryOfChoice after Todo, :mark_as_done do |todo|

    post_to_service(todo) end end
  43. AOP +Core is blissfully unaware of surroundings - Platforms need

    to know about internals !Beware of memory leaks +Useful when use cases on each platform are different
  44. Where to keep this logic?

  45. Cross Platform Gems But it requires a little bit of

  46. Cross Platform Gems • Tell sprockets where to look for

    files using Opal.append_path • use require as usual (it is translated into Sprockets directive)
  47. Cross Platform Gems • Use require only in the gem’s

    entry point • Add all required files in rubymotion config block
  48. Cross Platform Gems It literally takes 20 lines of code
  49. Let me show you the code!

  50. Ruby is alive

  51. Ruby Is taking over the world… … one platform at

    a time.
  52. Want to hear more? ! " #

    Michal Taszycki gunpowderlabs