“...I've been working since 2008 with Ruby / Ruby on Rails, love a bit of Elixir / Phoenix and learning Rust. I also poke through other people's code and make PRs for OpenSource Ruby projects that sometimes make it. Currently working for InPay...”

Rob Lacey (contact@robl.me)
Senior Software Engineer, Brighton, UK

extending a class included in a module

This seemed pretty straight forward to me.

module Something
  def api
   @api ||= Api.new
  end
  class Api
    def do_something
      :doing_something
    end
  end
end

class Thing
  include Something
  class Api
    def do_thing
      :doing_thing
    end
  end
end

Seems legitimate, just extend the class that I’ve included in my module.

2.1.2 :021 > Thing.new.api.do_thing
NoMethodError: undefined method `do_thing' for #<Something::Api:0x007f946546afe0>
	from (irb):21
	from /Users/rl/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'

Wrong! Hmmzz…. I guess the class that the module is instantiating from is the one in the module not the one included in my Thing class I need to ensure that I instantiate from the right one.

module Something
  def api
   @api ||= self.class::Api.new
  end
  class Api
    def do_something
      :doing_something
    end
  end
end

class Thing
  include Something
  class Api
    def do_thing
      :doing_thing
    end
  end
end
</pre></code>

Works, but hang on.

<pre><code>
2.1.2 :019 > Thing.new.api.do_thing
 => :doing_thing 
2.1.2 :020 > Thing.new.api.do_something
NoMethodError: undefined method `do_something' for #<Thing::Api:0x007fa60a4c1fc8>
	from (irb):20
	from /Users/rl/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'

The class is not using the class I’ve defined in my module at all.

module Something
  def api
   @api ||= self.class::Api.new
  end
  class Api
    def do_something
      :doing_something
    end
  end
end

class Thing
  include Something
  class Api < Something::Api
    def do_thing
      :doing_thing
    end
  end
end

Better,