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

Metaprogramming: From Zero to Hero. (URU meetup)

Metaprogramming: From Zero to Hero. (URU meetup)

How did I learn metaprogramming by creating a minimalist stubbing library called mocoso (https://github.com/frodsan/mocoso).

Francesco Rodríguez

April 08, 2014
Tweet

More Decks by Francesco Rodríguez

Other Decks in Programming

Transcript

  1. require "net/http" ! module RubyGems # ... ! def self.exists?(name)

    uri = URI(sprintf(URL, name)) res = Net::HTTP.get_response(uri) ! res.code == "200" end end
  2. test "creates if gem exists" do params = { "name"

    => "ricojson", "status" => "ok" } ! post("/gems", gem: params) ! assert_response(201) end
  3. test "errors if gem not exists" do post("/gems", gem: {

    name: "ruby" }) ! assert_response(422) end
  4. ʕ•ᴥ•ʔ ! • Minimalist. • Travel back in time. •

    No integration code. • No monkey patching.
  5. test "creates if gem exists" do stub(RubyGems, :exists?, true) #

    ... end ! test "errors if gem not exists" do stub(RubyGems, :exists?, false) # ... end
  6. struct RObject { struct RBasic basic; /* ... */ };

    ! struct RClass { struct RBasic basic; /* ... */ struct st_table *m_tbl; VALUE super; };
  7. ⊙﹏⊙ ! • Eigenclass. • Singleton class. • Object-specific class.

    • Virtual class. • Ghost class. • Metaclass. • Anonymous class.
  8. object = Object.new # => #<Object:…> ! ! object.singleton_class #

    => #<Class:#<Object:…>> ! object.singleton_class.class # => Class
  9. bar = Foo.new ! def bar.foo "bar" end ! #

    or ! class << bar def foo "bar" end end
  10. test "errors if gem not exists" do stub(RubyGems, :exists?, false)

    # ... end ! RubyGems.exists?("false") # => false
  11. def stub(object, method, result) metaclass = object.singleton_class original = object.method(method)

    ! metaclass.send(:define_method, method) do |*args| result end ! yield ensure metaclass.send(:undef_method, method) metaclass.send(:define_method, method, original) end
  12. test "errors if gem not exists" do stub(RubyGems, :exists?, false)

    # ... end ! RubyGems.exists?("really-exists") # => ...