Created
November 17, 2010 01:18
-
-
Save simonbaird/702840 to your computer and use it in GitHub Desktop.
Just some experiments with ruby modules
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# 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