How to extend a Ruby module using macro-like metaprogramming methods?

Consider the following extension (a template popularized by several Rails plugins over the years):

module Extension
  def self.included(recipient)
    recipient.extend ClassMethods
    recipient.send :include, InstanceMethods
  end

  module ClassMethods
    def macro_method
      puts "Called macro_method within #{self.name}"
    end
  end

  module InstanceMethods
    def instance_method
      puts "Called instance_method within #{self.object_id}"
    end
  end
end

If you want to expose this for each class, you can do the following:

Object.send :include, Extension

Now you can define any class and use the macro method:

class FooClass
  macro_method
end
#=> Called macro_method within FooClass

And instances can use instance methods:

FooClass.new.instance_method
#=> Called instance_method within 2148182320

But even if Module.is_a?(Object), you cannot use the macro method in the module.

module FooModule
  macro_method
end
#=> undefined local variable or method `macro_method' for FooModule:Module (NameError)

This is true even if you explicitly include the source Extensionin Modules Module.send(:include, Extension).

For individual modules, you can enable extensions manually and get the same effect:

module FooModule
  include Extension
  macro_method
end
#=> Called macro_method within FooModule

But how do you add macro-like methods to all Ruby modules?

+5
1

(, Rails )

, "". -, 1337 PHP h4X0rZ, Ruby. , (?) - Rails 3, , . Yehuda , -, Rails, -.

, :

Object.send :include, Extension

Object , :

class Object
  def instance_method
    puts "Called instance_method within #{inspect}"
  end
end

Ruby?

: Module:

class Module
  def macro_method
    puts "Called macro_method within #{inspect}"
  end
end

:

class FooClass
  macro_method
end
#=> Called macro_method within FooClass

FooClass.new.instance_method
#=> Called instance_method within #<FooClass:0x192abe0>

module FooModule
  macro_method
end
#=> Called macro_method within FooModule

10 16, 0 10 - .

, , , , - Object. :

module ObjectExtensions
  def instance_method
    puts "Called instance_method within #{inspect}"
  end
end

class Object
  include ObjectExtensions
end

module ModuleExtensions
  def macro_method
    puts "Called macro_method within #{inspect}"
  end
end

class Module
  include ModuleExtensions
end

16 , , , , , , , , 190000 StackOverflow , .

+22

All Articles