Skip to content

Instantly share code, notes, and snippets.

@bsodmike
Last active December 25, 2015 14:49
Show Gist options
  • Save bsodmike/6993736 to your computer and use it in GitHub Desktop.
Save bsodmike/6993736 to your computer and use it in GitHub Desktop.
Mixing in Namespaced Classes in Ruby, a Template Method implementation.

It's sometimes handy to setup a namespaced class when looking to utilise an overidden implementation of another class, i.e. template method pattern etc.

class MailProcessor

  class Importer < Foo::Bar::Importer

    # override inherited methods etc.

  end

  def perform
    MailProcessor::Importer.new.perform
  end
end

If you start to do override multiple classes, your base class is going to get rather large. Here's one way to clean to this up, let's move all of this into a simple mixin.

For the sake of this example, we are creating a ProcessorMixin which will namespace Processor under the base _klass.

# mail_processor/processor_mixin.rb
class MailProcessor

  module ProcessorMixin
    class << self

      def included(_klass)
        processor = Class.new(Foo::Processor) do
          # your custom implementation goes here; override as you will!
        end

        _klass.const_set :Processor, processor
      end

    end
  end

end

We only have to include our ProcessorMixin and it's quite simple to access it within our base class.

# mail_processor.rb
class MailProcessor
  
  require_relative 'mail_processor/processor_mixin'
  include ProcessorMixin

  def perform
    MailProcessor::Processor.new.perform
  end
end
@plexus
Copy link

plexus commented Oct 17, 2013

Why not just declare each in its own file?

# mail_processor/processor.rb
class MailProcessor::Processor < Foo::Processor
  # ...
end

@bsodmike
Copy link
Author

Hey @plexus,

Yes, that's certainly the 'obvious' way to go about it - it's just that I have more than one overridden processor being used; for the time being it feels more convenient to declare them in this manner rather than having an O(n) number of mail_processor/*_processor.rb files.

If you're overriding a single templated class, then the straightforward way is certainly recommended.

One downside to this approach is the fact that MailProcessor::Processor does not appear in YARD documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment