To be frankly, I don't have any previous experience with Ruby programming. I first looked at Ruby code(WSF/Ruby source), when I started to write WSF/Python and WSF/Python is still in its initial stage. When I started to implement WSDL mode for WSF/Python, to understand how it has done in WSF/Ruby, I looked at WSF/Ruby source. While I am reading through the code I found this ruby class called
WSProxy, which handles the all the WSDL mode stuff. It has only two methods, 'initialize' method and 'method_missing' method. When I saw this code I looked at
sample code that uses this WSProxy class. In that sample there is some code like following wich execute undefined method(because it's not on the actual implementation of WSProxy class) on instance of WSProxy. After a small discussion with the developer behind this code, I learn that actually the 'method_missing' method in WSProxy class is doing the magic. When we execute undefined method on Ruby's objects, all of these undefined calls are end up in this method. Inside this method you can get the name of that undefined methods and arguments given to it.
Ruby has this nice feature called method_missing method for every object in Ruby. Method missing is where your method request will end up if the method you called cannot be found. Here is a simple example:
class String
def method_missing(method, *arg)
puts "Called: #{method}"
return nil
end
end
puts "Hello".to_int()
When you execute it using ruby example.rb, you'll get the following out put:
This feature of ruby is so important when we want to dynamically deal with methods. The best example that I can give about usage of method_missing is implementing dynamic Web Service client. In this scenario what we are going to do is, give the WSDL, service name(if we have multiple services define in WSDL), port name(If we have multiple ports), operation name(web service's operation that we are going to call) and arguments to that operation. If we don't have feature like this, we have to implement a generic method which accepts, WSDL file, service name, port name, operation name and arguments and send a request to web service described by WSDL using user given parameters. The problem with this implementation is, user always call same method even he want to call different operation in web service. But using method_missing feature we can give nice API to user. For example, if we have operation call QueryPurchaseOder in Web Service we can give a API like this to user.
client = WSClient.new({"wsdl" => END_POINT}, LOG_FILE_NAME)
proxy = client.get_proxy
unless proxy.nil?
ret = proxy.QueryPurchaseOrder({"orderInfo"=> {"productName"=> "Testing",
"quantity" => 234,
"date" => "2003-12-34",
"orderNo" => 345}});
This is a dynamically generated API. what actually happens is, because there is no implementation for QueryPurchaseOder method, Ruby will call the method_missing method in WSProxy. Inside the method_missing we can give the handle to C layer with the operation name and arguments supply buy user like following:
def method_missing(name, *args)
if args.length == 1 then
arg = args[0]
if arg.kind_of? Hash then
result = WSFC::wsf_wsdl_request_function(@env,
@svc_client,
@options,
@wsdl,
name.to_s, arg,
@service_name,
@port_name,
@ruby_home)
return result
else
puts "only Hash is supported"
end
else
puts "dynamic function only support one argument"
end
return nil
end
After looking at this nice feature of Ruby and how WSF/Ruby used it to implement WSDL mode, I searched for a way to implementa this thing in Python. I have found
this nice articles describing how we can implement this feature in Python. He use __getattribute__ and __getattr__ methods which comes with every object in Python to implement method_missing feature in Python.
Related posts:
Sphere: Related Content
1 response so far ↓
1 Rubymethod lookup flow // Aug 9, 2008 at 4:24 pm
[...] a previous post I describe the advantages of Ruby method_missing feature. Here is good diagram which shows the flow of Ruby method [...]
Leave a Comment