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:
- Aspect the Ruby way The main purpose of this file is to be able...
- 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:



ShareThis
[...] 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 [...]