Fine Grained Mixins

Sapphire's fine grained mixins solve the multi-mixin problem without resorting to the static composition of Traits. In short, it allows you to selectively include, exclude or alias methods at the moment of inclusion.

Altering include

Whereas Ruby's include method includes all methods from a given module into a class, Sapphire alters the include method to accept a list of methods to selectively include. The following example illustrates a class that mixes in the method_a method from ModA, and the method_b method from ModB:
module ModA
   def method_a; end
   def method_b; end
end

module ModB
   def method_a; end
   def method_b; end
end

# Mixin 'method_a' from ModA, and 'method_b' from ModB
class ClassA
   include ModA, :method_a
   include ModB, :method_b
end

Explicit exclusion

If a module has a large number of methods, and a programmer wants all but one or two them, the above notation quickly becomes cumbersome. Therefore, Sapphire accepts an exclude parameter, which accepts an array of method names to explicitly exclude from the mixed in module. The rest of the module's methods are included. The following example excludes method_a and method_e from being mixed into ClassA, accepting the rest of the methods:
module ModA
   def method_a; end
   def method_b; end
   def method_c; end
   def method_d; end
   def method_e; end
end

# Mixin all methods except 'method_a' and 'method_e'
class ClassA
   include ModA, :exclude => [:method_a, :method_e]
end

On the fly aliasing

In some cases a programmer may want the functionality of a particular method from a given module, but at the same time needs to avoid a name collision. Sapphire's include method accepts the alias keyword parameter that allows you to alias a method name on the fly, including the method by the alias rather than its original name. The following example mixes in method_a from ModA into ClassA, but with the name my_method_a:

module ModA
   def method_a; end
   def method_b; end
end

# Mixin 'method_a' from ModA, but as 'my_method' instead.
class ClassA
   include ModA, :alias => [:method_a, :my_method]
end

a = ClassA.new
a.my_method # Legal

Rules

  • You cannot both include and exclude the same method or an error is raised.
  • An include without any arguments is the same as Ruby's current include mechanism.

Also available in: HTML TXT