Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby - Write Once, Run Anywhere - Polyconf 2014

Ruby - Write Once, Run Anywhere - Polyconf 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 31, 2014


  1. Ruby - Write Once, Run Anywhere Michal Taszycki @mehowte GunpowderLabs

  2. Ruby is dead

  3. Ruby is alive

  4. Who wants to play a game?

  5. Who wants to play a game?

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

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

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

  9. But now… We have the technology!

  10. But now… We can write cross-platform applications!

  11. Opal.rb

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

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

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

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

  16. 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
  17. Is any of them really a Ruby == ? ==

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

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

    • symbols are strings • regexps differ • All numbers are floats • no for loop yet ;)
  20. 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)
  21. Is any of them really a Ruby

  22. They’re Ruby enough!

  23. Cross Platform Ruby

  24. Cross Platform Ruby

  25. Interactions

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

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

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

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

  30. 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)
  31. Interactions

  32. 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)
  33. Interactions

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

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

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

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

    mark_as_done self.done = true self.class.saver.save(self) end end Abstract interface
  38. Abstract interface Todo.saver = TodoSaver.new(DatabaseAdapter.new) todo.mark_as_done ! # or !

    Todo.saver = TodoSaver.new(RestAdapter.new) todo.mark_as_done
  39. Abstract interface +Well defined interaction - Core needs to know

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

    trigger(:marked_as_done, self) end end
  41. 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
  42. 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
  43. AOP class Todo def mark_as_done self.done = true end end

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

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

    post_to_service(todo) end end
  46. 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
  47. Where to keep this logic?

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

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

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

    entry point • Add all required files in rubymotion config block
  51. Cross Platform Gems It literally takes 20 lines of code

  52. Let me show you the code!

  53. Ruby is alive

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

    a time.
  55. Want to hear more? twitter.com/mehowte michal@gunpowderlabs.com ! " github.com/mehowte #

    Michal Taszycki gunpowderlabs crossplatformruby.com