!Electronic || !Bionic || !Ultrasonic

From other programming language I know a interesting feature; the ‘with’ keyword. It allows to write some code in the environment within the bindings of the passed object.

Ruby has myriad of ways of doing something and leaves you plenty of freedom to choose your style. I wanted a more readable coherent approach for such an important feature I use all the time.

x_eval

Ruby has a good portion of introspection, an methods to allow the manipulation of Objects and since everything treated as an Object, even the Class of an object can be handled as such.

in the spirit of not repeating ourself, instead of

	some_object.setTitle "Hello World"
	some_object.setSomeThing new_value
	some_object.setTest 11313

we could write something like this:

	some_object.instance_eval do
		setTitle "Hello World"
		setSomeThing new_value
		setTest 1313
	end

and indead we cann also f.ex add methods to that object

	some_object.instance_eval do
		def new_method_foo
			puts "I am method foo"
		end
	end
 
	some_object.new_method_foo  => "I am method foo"

we can also add the method to the class, so that every isntance of that class
gets access to the method:

	some_object.class.class_eval do
		def new_method_foo
			puts "I am method foo:
		end
	end
 
	some_object.new_method_foo  => "I am method foo"
 
	# of same class as some_object
	other_object.new_method_foo => "I am method foo"

we can add the method to the class e.g as class method:

	some_object.class.class.class_eval do
		def net_method_foo
			puts "I am class method foo"
		end
	end
 
	some_object.class.new_method_foo => "I am method foo"
	every_object.class.new_method_foo => "I am method foo"

for the last two examples we have to use the method class_eval instead of instance_eval to achieve the same notation as instance_eval. So why not introduce a small syntactic keyword?

meta_class

	class B
	end
	class A << B
	end

Here is the hierarchy of class A:

      Class
      Class B
      B #accessed via A.class
      Class: A #accessded via class << self ; self; end
      A # accessed via self or A depending on context

      class A is a subclass of B as such A.class returns the parent class B. B is a subclass of Class because we didn’t specify any parent class to inherit from. Between our A class an its parent class B there pups up the ‘Class: A’, this the meta class of our class. If we add a method to class B, this method will be available to every subclass of it. But we can also add a method to the meta class of A; so that it will only be available to the subclasses of A and B don’t get modified.

      What we really want is a easier way to access the meta class. In such a way like we can access the direct parent class.

      	class Class
      		def meta_class
      			class << self; self; end
      		end
      	end
      	class Object
      		def meta_class
      			class << self; self; end
      		end
      	end
      	A.class.class => Class
      	A.class.meta_class => <Class: B>
      	A.class  => B
      	A.meta_class => <Class: A>
      	A => A

      With

      We can define a simple method ‘with’ which accept an object and a code block. It executes the code block in the environment of the passed object. As we want
      the same behavior for objects and classes, we call instance_eval for objects but if we pass a Class we will call class_eval.

      	def with(obj, &code)
      		if obj.kind_of?Class
      			obj.class_eval &code
      		else
      			obj.instance_eval &code
      		end

      Now here the same examples rewritten using the with method:

      in the spirit of not repeating ourself, instead of

      	some_object.setTitle "Hello World"
      	some_object.setSomeThing new_value
      	some_object.setTest 11313

      we could write something like this:

      	with some_object do
      		setTitle "Hello World"
      		setSomething new_value
      		setTest 1313
      	end

      and indead we cann also f.ex add methods to that object

      	with some_object do
      		def new_method_foo
      			puts "I am method foo"
      		end
      	end
       
      	some_object.new_method_foo  => "I am method foo"

      we can also add the method to the class, so that every instance of that class
      gets access to the method:

      	with some_object.class do
      		def new_method_foo
      			puts "I am method foo:
      		end
      	end
       
      	some_object.new_method_foo  => "I am method foo"
       
      	# of same class as some_object
      	other_object.new_method_foo => "I am method foo"

      we can add the method to the class e.g as class method:

      	with some_object.class.class do
      		def net_method_foo
      			puts "I am class method foo"
      		end
      	end
       
      	some_object.class.new_method_foo => "I am method foo"
      	every_object.class.new_method_foo => "I am method foo"

      And at last we can add the method to the meta class:

      	with some_object.meta_class do
      		def new_method_foo
      			puts "I am foo"
      		end
      	end
       
      	some_object.class.new_method_foo => "I am method foo"
      Related posts:
      1. Aspect the Ruby way The main purpose of this file is to be able...
May 18, 2009
ad

[...] the article Keyword With I present here how I write a Module to be included an a class. It has to extend the class with [...]

Email Icon Facebook Icon Twitter Icon Share this IconShareThis Follow Ironicwolf on Twitter