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

Multiverse Ruby

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Multiverse Ruby

Slides from my talk by the same name at RubyKaigi 2023, given in Japanese.

shioyama/im
shioyama/rails_on_im

Avatar for Chris Salzberg

Chris Salzberg

May 12, 2023
Tweet

More Decks by Chris Salzberg

Other Decks in Programming

Transcript

  1. n = 10 a, b = 0, 1 n.times do

    a, b = b, a + b end puts a
  2. module Fibonacci def self.fib(n) a, b = 0, 1 n.times

    do a, b = b, a + b end a end end
  3. module Fibonacci def self.fib(n) a, b = 0, 1 n.times

    do a, b = b, a + b end a end end code
  4. module Fibonacci def self.fib(n) a, b = 0, 1 n.times

    do a, b = b, a + b end a end end architecture
  5. // variable.c:138 static VALUE make_temporary_path(VALUE obj, VALUE klass) { VALUE

    path; switch (klass) { case Qnil: path = rb_sprintf("#<Class:%p>", (void*)obj); break; case Qfalse: path = rb_sprintf("#<Module:%p>", (void*)obj); break; default: path = rb_sprintf("#<%"PRIsVALUE":%p>", klass, (void*)obj); break; } OBJ_FREEZE(path); return path; }
  6. mod

  7. require "my_gem" # my_gem.rb require "foo" require "bar" # foo.rb

    # bar.rb require require require require require
  8. mod = import "my_gem" # my_gem.rb require "foo" require "bar"

    # foo.rb # bar.rb require require require require require load load load load load load load
  9. mod = import "my_gem" # my_gem.rb require "foo" require "bar"

    # foo.rb # bar.rb require require require require require load load load load load load load
  10. im i isolated solated m module odule autoloader autoloader i

    isolated solated m module odule autoloader autoloader
  11. Zeitwerk: Code Loader lib/my_gem.rb → MyGem lib/my_gem/foo.rb → MyGem::Foo lib/my_gem/bar_baz.rb

    → MyGem::BarBaz lib/my_gem/woo/zoo.rb → MyGem::Woo::Zoo Object:: Object:: Object:: Object::
  12. lib/my_gem.rb → MyGem lib/my_gem/foo.rb → MyGem::Foo lib/my_gem/bar_baz.rb → MyGem::BarBaz lib/my_gem/woo/zoo.rb

    → MyGem::Woo::Zoo Im: Isolated Code Loader mod:: mod:: mod:: mod:: temporary root
  13. mod = import "my_gem" mod::MyGem::Foo #=> loads "lib/my_gem/foo.rb" mod::MyGem::Foo::BarBaz #=>

    loads "lib/my_gem/foo/bar_baz.rb" mod::MyGem::Foo::Woo::Zoo #=> loads "lib/my_gem/foo/woo/zoo.rb"
  14. # lib/my_gem.rb (main file) require "zeitwerk" loader = Zeitwerk::Loader.for_gem loader.setup

    # ready! module MyGem # ... end loader.eager_load # optionally
  15. # lib/my_gem.rb (main file) require "im" loader = Im::Loader.for_gem loader.setup

    # ready! module loader::MyGem # ... end loader.eager_load # optionally define under loader, not at top-level!
  16. def require(path) filetype, feature_path = $:.resolve_feature_path(path) if (loader = Im::Registry.loader_for(path))

    # ... $LOADED_FEATURES << feature_path begin load path, loader rescue => e $LOADED_FEATURES.delete(feature_path) raise e end
  17. def require(path) filetype, feature_path = $:.resolve_feature_path(path) if (loader = Im::Registry.loader_for(path))

    # ... $LOADED_FEATURES << feature_path begin load path, loader rescue => e $LOADED_FEATURES.delete(feature_path) raise e end
  18. def require(path) filetype, feature_path = $:.resolve_feature_path(path) if (loader = Im::Registry.loader_for(path))

    # ... $LOADED_FEATURES << feature_path begin load path, loader rescue => e $LOADED_FEATURES.delete(feature_path) raise e end
  19. def require(path) filetype, feature_path = $:.resolve_feature_path(path) if (loader = Im::Registry.loader_for(path))

    # ... $LOADED_FEATURES << feature_path begin load path, loader rescue => e $LOADED_FEATURES.delete(feature_path) raise e end 🙈
  20. assert loader::A X = loader::A assert loader::A assert loader::A::B assert

    loader::A::B::C assert_equal(X::B::C, loader::A::B::C) FAIL ❌
  21. { "<#Im::Loader ...>" ⇨ ... "MyFoo" ⇨ ... "MyFoo::Bar" ⇨

    ... ... } cpath Object.const_added(:MyFoo)
  22. assert loader::A X = loader::A assert loader::A assert loader::A::B assert

    loader::A::B::C assert_equal(X::B::C, loader::A::B::C) PASS ✅