Skip to content

gdeoliveira/extensible

Repository files navigation

Extensible

Gem Version Build Status Code Climate Test Coverage Inline docs

Use Extensible on your custom extensions in order to get the following set of advantages over traditional extensions that override the Module#extended method directly:

  • Calls to super are handled internally to ensure all your extensible extensions are properly initialized.
  • Your extensible extensions will be automatically able to become the base of other, more specific extensions while proper initialization is maintained by simply including them.
  • Bundle several extensible extensions in a single module by including them and they will all be correctly initialized when extending the bundler module.

Specific examples for each of these scenarios can be found in the usage section.

Installation

Add this line to your application's Gemfile:

gem "extensible"

And then execute:

$ bundle

Or install it yourself as:

$ gem install extensible

When should I use Extensible?

You should use Extensible every time you're implementing a module that is intended to be used as an extension for a module or a class and that extension needs to have some initialization code.

In short: if you are going to override Module#extended, use Extensible instead.

Usage

Basic

Creating an extensible extension module is, arguably, simpler than creating a traditional extension that overrides Module#extended. Note that we do not need to call super within the code block since it will be called "under the hood" before the code is executed:

module MyExtension
  extend Extensible
  when_extended {|m| puts "#{self} has extended #{m}." }
end

As you would expect, this is what happens when you use your extensible extension in a class (or module):

class MyClass
  extend MyExtension
end  #=> MyExtension has extended MyClass.

Extending extensions

The extensions you create using Extensible are "extensible" in the sense that you (or someone else) can use them as the base for other, more specific extensions. The best bit is you get this at no additional cost. Simply include them and extend away!

Suppose we have a base extension that sets an instance variable that holds the reversed name of the module or class extending it:

module MyBaseExtension
  extend Extensible
  when_extended do |m|
    m.instance_variable_set(:@reversed_name, m.to_s.reverse)
  end
end

Now we can use MyBaseExtension on its own, but we can also extend it to, for example, create a reader method for the @reversed_name variable by including it on our more specific MySubExtension:

module MySubExtension
  include MyBaseExtension
  attr_reader :reversed_name
end

We can now extend MySubExtension ensuring that the initialization routine of MyBaseExtension is executed as expected:

class MyClass
  extend MySubExtension
end

MyClass.reversed_name  #=> "ssalCyM"

Note: MySubExtension could have (if needed) extended Extensible to provide its own initialization routine. In this case both initialization routines (the one for MyBaseExtension and the one for MySubExtension) would have been executed when MyClass extended it.

Bundling extensions

Traditional extensions that override the Module#extended method work correctly as long as they are explicitly extended in the module or class that will ultimately use them. This can become really cumbersome really fast when you want to apply several extensions to a set of different modules or classes.

Using extensible extensions you can bundle many of them within a single module, and then extend all of them at the same time by extending the bundler module.

Suppose you have two extensions (A and B) that you want to bundle together:

module A
  extend Extensible
  when_extended { puts "A was extended!" }
end

module B
  extend Extensible
  when_extended { puts "B was extended!" }
end

Simply include them in your bundler module:

module Bundle
  include A
  include B
end

And extend it!

module MyClass
  extend Bundle
end  #=> A was extended!
     #=> B was extended!

Contributing

  1. Fork it ( https://github.com/gdeoliveira/extensible/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am "Add some feature")
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

About

Ruby extensions made easy

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published