vinod's erudition

we learn everything from failure not from success so keep failing

Home Ruby Rails Javascript Python Agentic AI

Ghost Methods magic of Metaprogramming

Posted on February 04, 2014 by vinod

Good Morning !!!!! Today let us discuss how to handle methods which are not defined using method_missing() magic of metaprogramming.what happens when you go to a house and enquire about people who is not present in the house definitely they will say “no person in that name here” same in ruby when you call a method which is not really present ,ruby searches it in base class and searches up to ancestor chain up to object and then enters in to kernel.if ruby does not find the method anywhere then it admit the failure by surrendering in to method_missing() method which is instance method of Kernel .which every object inherits . It will throw you “No Method error”

but we are fortunate to use Ruby which provide metaprogramming features to handle method that really doesnt exist by overriding method_missing() .

####GHOST METHODS if you call a methods that really doesnt exist Ruby handles it by method_missing() which handles the method and perfroms the necessaary action these are called ghost methods

“if they ask you something and you dont understand do this”

class Hunter 
	def method_missing(method_name,*args) 
 	  puts " name #{method_name} and his weight,height : (#{args.join(',')})" 
 	  puts "block is presend" if block_given? 
	end 
end 

hunt=Hunter.new 
hunt.vinod 82,180 do 
puts "this is block" 
end 

Here in below example we are refactoring the organization puzzle using method_missing where Ghost method is implemented.

class DataSource  #DataSource where it stores the information about resources and project of every domain


 def get_ruby_resource(location_id)
 	"23"
 end

 def get_ruby_projects(location_id)
 	"Clear trip,Twitter,Github"
 end
 
 def get_java_resource(location_id)
 	"50"
 end

 def get_java_projects(location_id)
 	"flipkart,google+"
 end

 def get_php_resource(location_id)
 	"43"
 end

 def get_php_projects(location_id)
 	"facebook,orkut"
 end

end

class RefDomain

	
	def initialize(location_id,data_source)
		@id=location_id
		@ds=data_source
		#@ds.methods.grep(/^get_(.*)_projects$/){ RefDomain.define_domain $1 }  #here grep filets the methods to matches the particular pattern and stores in $1

	end

	def method_missing(name)
		super if !@ds.respond_to?("get_#{name}_resource")  # pattern doesnt match then call method_missing() in kernel

		resource=@ds.send "get_#{name}_resource",@id  
		ojects=@ds.send "get_#{name}_projects",@id
		conclusion="#{name.to_s.upcase!}:#{resource} resources and #{projects}"
		return "enough #{conclusion}" if resource.to_i >30
		conclusion
	end
	
end
d=RefDomain.new(2,DataSource.new)
puts d.ruby # > RUBY:23 resources and Clear trip,Twitter,Github

puts d.java # > enough JAVA:50 resources and flipkart,google+

puts d.php # > enough PHP:43 resources and facebook,orkut

puts d.net

####Explanation: Here when a unknown method is called it calls the method_missing() and first it checks whether the method name is present in the Datasource if not then call ‘super’ which calls the method_missing() in kernel which throws no method error otherwise it will execute the corresponding method in Datasource.