Search code examples
rubysoapwsdlsoap4r

Accessing SOAP Service with soap4r not able to access contents of returned objects


So I need to access this service from my rails app. I'm using soap4r to read the WSDL and dynamically generate methods for accessing the service.

From what I've read, I should be able to chain methods to access the nested XML nodes, but I can't get it to work. I tried using the wsdl2ruby command and read through the generated code. From what I can tell, the soap library is not generating these accessor methods. I'm pretty new to ruby, so I don't know if I'm just missing something?

I know when I inspect the element, I can see the data I want. I just can't get to it.

For instance if I use the following code:

require "soap/wsdlDriver"
wsdl = "http://frontdoor.ctn5.org/CablecastWS/CablecastWS.asmx?WSDL"
driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
response = driver.getChannels('nill')
puts response.inspect

I get the following output:

ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}binding
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}operation
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}body
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}address
#<SOAP::Mapping::Object:0x80b96394 {http://www.trms.com/CablecastWS/}GetChannelsResult=#<SOAP::Mapping::Object:0x80b96178 {http://www.trms.com/CablecastWS/}Channel=[#<SOAP::Mapping::Object:0x80b95f5c {http://www.trms.com/CablecastWS/}ChannelID="1" {http://www.trms.com/CablecastWS/}Name="CTN 5">, #<SOAP::Mapping::Object:0x80b9519c {http://www.trms.com/CablecastWS/}ChannelID="2" {http://www.trms.com/CablecastWS/}Name="PPAC 2">, #<SOAP::Mapping::Object:0x80b94620 {http://www.trms.com/CablecastWS/}ChannelID="14" {http://www.trms.com/CablecastWS/}Name="Test Channel">]>>

So the data is definitely there!

Here is the code generated by wsdl2ruby for the method being used above:

# {http://www.trms.com/CablecastWS/}GetChannels
class GetChannels
  def initialize
  end
end

# {http://www.trms.com/CablecastWS/}GetChannelsResponse
#   getChannelsResult - ArrayOfChannel
class GetChannelsResponse
  attr_accessor :getChannelsResult

  def initialize(getChannelsResult = nil)
    @getChannelsResult = getChannelsResult
  end
end

Sorry for the long post, I figured the more info the more likely someone can point me in the right direction.

Thanks

-ray


Solution

  • Answer

    require "soap/wsdlDriver"
    wsdl = "http://frontdoor.ctn5.org/CablecastWS/CablecastWS.asmx?WSDL"
    driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
    response = driver.getChannels('nill')
    
    for item in response.getChannelsResult.channel
      puts item.name
      puts item.channelID
    end
    

    How I got the Answer

    You can figure out the methods of response via

    response.methods
    

    This will get you a long list of methods that are hard to sort through, so I like to subtract out the generic methods. Ruby lets you subtract arrays.

    response.methods - Object.new.methods
    

    Using this technique, I found the getChannelsResult method for response. I repeated the process

    resonse.getChannelsResult.methods - Object.new.methods
    

    I found the channel method for its result. Again!

    response.getChannelsResult.channel.methods - Object.new.methods
    

    This returned a bunch of methods including: sort, min, max etc. So I guessed Array. A simple confirmation was in order

    response.getChannelsResult.channel.class
    

    Sure enough it returned Array. To make life simple, I just worked with the first item of the array to get its methods

    response.getChannelsResult.channel.first.methods - Object.new.methods
    

    Whoalla, I found two more methods "name" and "channelID"