Skip to content

Instantly share code, notes, and snippets.

@simonbaird
Created November 17, 2010 01:18
Show Gist options
  • Save simonbaird/702840 to your computer and use it in GitHub Desktop.
Save simonbaird/702840 to your computer and use it in GitHub Desktop.
Just some experiments with ruby modules
#
# 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)
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment