|
# |
|
# Example 1 |
|
# |
|
# There are two modules, one for instance methods and one for class methods |
|
# Use 'include' and 'extend' separately |
|
# |
|
module Foo1Instance |
|
def foo; "instance foo (#{self.class.name})"; end |
|
end |
|
|
|
module Foo1Static |
|
def foo_static; "static foo"; end |
|
end |
|
|
|
class MyClass1 |
|
include Foo1Instance |
|
extend Foo1Static |
|
end |
|
|
|
# |
|
# Example 2 |
|
# |
|
# Kinda the same except there is a container module |
|
# |
|
module Foo2 |
|
module InstanceMethods |
|
def foo; "instance foo (#{self.class.name})"; end |
|
end |
|
|
|
module ClassMethods |
|
def foo_static; "static foo"; end |
|
end |
|
end |
|
|
|
class MyClass2 |
|
include Foo2::InstanceMethods |
|
extend Foo2::ClassMethods |
|
end |
|
|
|
|
|
# |
|
# Example 3 |
|
# |
|
# There is one module with an inner module for the static methods. |
|
# The module defines the include method to automatically extend |
|
# using the inner module |
|
# |
|
module Foo3 |
|
def foo; "instance foo (#{self.class.name})"; end |
|
|
|
module ClassMethods |
|
def foo_static; "static foo"; end |
|
end |
|
|
|
# Make it so when this module is included it will also extend... |
|
def self.included(base) |
|
base.extend ClassMethods |
|
end |
|
end |
|
|
|
class MyClass3 |
|
include Foo3 |
|
end |
|
|
|
# |
|
# Example 4 |
|
# |
|
# Same again but in reverse (just to satisfy my curiousity) |
|
# |
|
# Automatically include some stuff when extending |
|
# |
|
module Foo4 |
|
def foo_static; "static foo"; end |
|
|
|
module InstanceMethods |
|
def foo; "instance foo (#{self.class.name})"; end |
|
end |
|
|
|
# Make it so when this module is included it will also extend |
|
def self.extended(base) |
|
#base.include InstanceMethods # <- private method `include' called for MyClass4:Class (NoMethodError) |
|
# so use send.. |
|
base.send :include, InstanceMethods |
|
end |
|
end |
|
|
|
class MyClass4 |
|
extend Foo4 |
|
end |
|
|
|
# |
|
# Example 5 |
|
# |
|
# Since ruby can do anything, let's define an include_and_extend method |
|
# |
|
# |
|
class Class |
|
def include_and_extend_1(the_module) |
|
include the_module |
|
extend the_module::ClassMethods |
|
end |
|
end |
|
|
|
module Foo5 # like Foo3 without the def included magic |
|
def foo; "instance foo (#{self.class.name})"; end |
|
|
|
module ClassMethods |
|
def foo_static; "static foo"; end |
|
end |
|
end |
|
|
|
class MyClass5 |
|
include_and_extend_1 Foo5 |
|
end |
|
|
|
# |
|
# Example 6 |
|
# |
|
# Improve (?) include_and_extend using const_get |
|
# |
|
class Class |
|
# Incase you want to use something other than ClassMethods, lets use an optional arg |
|
def include_and_extend_2(the_module,class_methods=:ClassMethods) |
|
include const_get(the_module) |
|
extend const_get(the_module).const_get(class_methods) |
|
end |
|
end |
|
|
|
class MyClass6 |
|
include_and_extend_2 :Foo5, :ClassMethods |
|
end |
|
|
|
# |
|
# Example 7 |
|
# |
|
# Improve (?) include_and_extend again by checking for existance of the inner modules... |
|
# |
|
class Class |
|
def include_and_extend(the_module,options={}) |
|
options[:instance_methods] ||= :InstanceMethods |
|
options[:class_methods] ||= :ClassMethods |
|
# Mainly include but be flexible |
|
main_module = const_get(the_module) |
|
include main_module # for an extend_and_include method, change this to extend main_module |
|
include main_module.const_get(options[:instance_methods]) if main_module.const_defined?(options[:instance_methods]) |
|
extend main_module.const_get(options[:class_methods]) if main_module.const_defined?(options[:class_methods]) |
|
end |
|
end |
|
|
|
class MyClass7 |
|
include_and_extend :Foo5 |
|
end |
|
|
|
# |
|
# Example 8 |
|
# |
|
# Test the optional args for include_and_extend... |
|
# |
|
module Foo8 |
|
def foo; "instance foo (#{self.class.name})"; end |
|
module YipInstance |
|
def foo2; "instance foo2 (#{self.class.name})"; end |
|
end |
|
module YipClass |
|
def foo_static; "static foo"; end |
|
end |
|
end |
|
|
|
class MyClass8 |
|
include_and_extend :Foo8, :instance_methods => :YipInstance, :class_methods => :YipClass |
|
end |
|
|
|
|
|
|
|
#------------------------------------------------------------------------------- |
|
# Does it work? |
|
# |
|
[MyClass1, MyClass2, MyClass3, MyClass4, MyClass5, MyClass6, MyClass7, MyClass8].each do |klass| |
|
puts "#{klass.new.foo}, #{klass.foo_static}" |
|
end |
|
|
|
# The extra instance method from Foo8... |
|
puts MyClass8.new.foo2 |
|
|
|
|
|
# |
|
# |
|
# Output |
|
# |
|
# ~> ruby include_and_extend_experiments.rb |
|
# instance foo (MyClass1), static foo |
|
# instance foo (MyClass2), static foo |
|
# instance foo (MyClass3), static foo |
|
# instance foo (MyClass4), static foo |
|
# instance foo (MyClass5), static foo |
|
# instance foo (MyClass6), static foo |
|
# instance foo (MyClass7), static foo |
|
# instance foo (MyClass8), static foo |
|
# instance foo2 (MyClass8) |
|
# |