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

Ruby - Write Once, Run Anywhere

Ruby - Write Once, Run Anywhere

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

September 12, 2014


  1. Ruby Is dead.

  2. Ruby Is now more alive than ever!

  3. Who am I? twitter.com/mehowte michal@gunpowderlabs.com ! " github.com/mehowte # Michal

    Taszycki gunpowderlabs crossplatformruby.com
  4. Remember Javascript? Meteor

  5. But now… We have the technology!

  6. Opal.rb

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

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

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

    will be available soon • Native performance • Version > 2.0, actively developed • Widely used in production
  10. mruby

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

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

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

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

  17. They’re Ruby enough!

  18. Cross Platform Ruby

  19. Cross Platform Ruby

  20. Interactions

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

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

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

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

  25. 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)
  26. Interactions

  27. 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)
  28. Interactions

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

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

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

  32. 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
  33. Abstract interface Todo.saver = TodoSaver.new(DatabaseAdapter.new) todo.mark_as_done ! # or !

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

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

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

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

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

    post_to_service(todo) end end
  41. 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
  42. Cross Platform Gems • Tell sprockets where to look for

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

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

  45. Suggestions 1.Make a folder named as an app 2.Rename app

    folders to platform names 3.Keep them together with gems 4.Keep each of those in separate repositories 5.Use semantic versioning (if you work in teams) 6.Break Replace rules with better ones
  46. Is it for everyone? (No but there are many use

  47. Does it work? (Hell yes!)

  48. Ruby is alive

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

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

    Michal Taszycki gunpowderlabs crossplatformruby.com