This source comprises two files:
require-include.rb and requireme.rb
First up, we need something to ‘require’. Save this as requireme.rb.
# Let people know we're running
puts "REQUIRED"
# Add a new method on Object. This will add the methods
# to All objects, regardless where we 'require' this.
class Object
def new_method
self.class
end
end
# Def a method on 'self', which will be the class whose
# definition we require this inside of.
def other_method
"Not so new"
end
# The important point is that 'required' code works the same as the rest
# of Ruby, with respect to the scope in which it executes - self here
# is 'main' (the toplevel).
puts "In 'requireme', self is #{self.inspect}"
And we need something to require it (save as require-include.rb):
# require an external module (ruby standard in ths case). At the top-level,
# so it's methods are available everywhere.
require "fileutils"
# Lets' mix a new method into an existing class, 'Class'
module NewClassMethod
def new_attr_accessor(*syms)
puts "Making accessors: #{syms.inspect}"
attr_accessor *syms
end
end
class Class
include NewClassMethod
end
# Make our own module to include in a new class
module MyFileUtils
def print_wd
puts "#{self.class.name} #{self.object_id} (#{self.to_s})", "Workdir: #{FileUtils.pwd()}"
end
end
class MyClazz
# Right now, 'self' is a class, so we can call our new class method
new_attr_accessor :myattr
include MyFileUtils
# require is just a method, and can be called anywhere.
# but the scoping remains the same as any other code.
require 'requireme.rb'
# Call our new method on 'Object'
def call_new_method
Object.new.new_method
end
end
# The included methods *do* become part of the class they're included to.
b = MyClazz.new
b.print_wd
# The methods added to Object are available of course on every Object,
# since redefining a class always redefines that class.
p b.call_new_method
p Object.new.new_method
# Our 'other method' (a straight def in requireme) is defined on Kernel,
# which mixes in private methods to every class, so we can't call it
# like:
begin
b.other_method
rescue NoMethodError => ex
puts "Got expected #{ex}"
end
# We could to resort to 'send' if we really care.
p b.send(:other_method)
# But, since it's a private kernel method the intention is really
# that it be called only without a receiver.
p other_method
# This won't print 'REQUIRED' again - 'require' only loads stuff once.
# If you wanted to have it loaded again and again, you could use 'load'
# instead.
10.times { require 'requireme' }
Running this outputs:
Making accessors: [:myattr]
REQUIRED
In 'requireme', self is main
MyClazz -604428724 (#<MyClazz:0xb7f24c98>)
Workdir: /home/rosco/dev/rpot/doc/res/code/noob
Object
Object
Got expected private method `other_method' called for #<MyClazz:0xb7f24c98>
"Not so new"
"Not so new"

