Monday 16 September 2013

Metaprogramming with ruby


1) eval , #{} and their difference.

eval  is used to evaluate the string as expression.
#{} is used to delimit the expressions in a double-quoted string.

At first they both look same however there is a difference between both. Let me explain this with the help of an example.
Suppose we have a variable
exp = "2*4"
Now the output of eval(exp) will be 8
Where as output of  "#{exp}"  will be 2*4

2) instance_eval, module_eval and class_eval

instance_eval can be used to access the instance variable of an object.

For example:-
class Test
  def initialize
  @variable = "hello"
  end
end

obj = Test.new
obj.instance_eval do 
 puts @variable # Output-> hello
end
instance_eval can also be used for creating class methods

For example:-
class Test
end

Test.instance_eval do 
 def hello
   puts "hello world"
 end
end

Test.hello # output => hello world
Like instance_eval, module_eval and class_eval are used to access class variable from outside a class.
Both module_eval and class_eval operates on modules and class rather than their objects.

For Example:-
class Test
 @@variable = "hello"
end

 puts Test.class_eval(@@variable) # Output-> hello
module_eval and class_eval are also used to create new instance methods.
For Example:-
class Test
end

Test.class_eval do 
 def hello
   puts "hello world"
 end
end
obj = Test.new
obj.hello # output => hello world

3) instance_variable_get and instance_variable_set
instance_variable_get, as the name suggests, is used to retrieve the value of any instance variable.
It takes the the variable name as symbol argument

For example:-
class Test
  def initialize
  @variable = "hello"
  end
end

obj = Test.new
obj.instance_variable_get(:@variable) # Output => hello
instance_variable_set, as the name suggests, is used to set the value of any instance variable.
It takes a symbol argument as variable name and second argument which is the variable value

For example:-
class Test
  def initialize
  @variable = "hello"
  end
end

obj = Test.new
obj.instance_variable_set(:@variable,"hello world")
4) send method

send method is used to call a method of the same name as specified as the first argument(which is in symbol format)

For Example:-
@variable = "test"
puts( @variable.send(:reverse)) # this will call the reverse method for that string
You can also pass the any number of arguments after specifying the first argument which is the method name.

For Example:-
class Test
  def sum (a,b)
  return a+b
  end
end

obj = Test.new
obj.send(:sum, 4 , 5) # Output =>9
5) define_method 

This method can be used to define new methods during run time.
For Example:-
 class A
   define_method("test") do ||
     puts "hello"
   end
 end
b= A.new
b.test #output => hello
Another Example:-
Here we are also passing some arguments to the newly created method
 class Array
   define_method(:aNewMethod, lambda{ |*args| puts( args.inspect) } end
[].aNewMethod([1,2,3]) #Ouput [1,2,3]
6) remove_method

You can also remove the existing methods or method you created by using the remove_method.

For Example:-
puts("hello".reverse)
class String
remove_method(:reverse)
end
puts("hello".reverse) # Output => undefined method error!
Note: - If a method with the same name is defined for an ancestor of that class, the ancestor class method is not removed

7) method_missing


There might be the times when you may try to execute a method which is not defined, this will throw an error and cause the program to exit. To handle this situation you can write your own method called method_missing with an argument to which the missing method name is assigned.
class Test
  def method_missing (method_name)
    puts("#{method_name} do not exist")
  end
end

obj = Test.new
obj.new_method # Output = > new_method do not exist

8) Frozen Object
 
Ruby provides you a facility to freeze an object so that it cant be modified further. The object once frozen cannot be modified, if tried to do so it will raise a TypeError exception.
variable = "Hello" 
variable << "world" 
variable.freeze 
variable << " !!!" # Error: "can't modify frozen string (TypeError)"
Please note once an object is frozen it cant be be undone.

No comments:

Post a Comment