#<SOAP::Mapping::Object:0x2ea9fe8>
#<SOAP::Mapping::Object:0x2e9b9c0>
#<SOAP::Mapping::Object:0x2e88b20>
I can subject these to "p" or "pp" and see what they are:
[#<SOAP::Mapping::Object:0x1719b58 {}MemberID=3 {}Name="foo3"
{}Address="bar3">,
#<SOAP::Mapping::Object:0x170f0ac {}MemberID=1 {}Name="foo1"
{}Address="bar1">,
#<SOAP::Mapping::Object:0x17059a4 {}MemberID=2 {}Name="foo2"
{}Address="bar2">]
But I can't seem to figure out how to use "to_s" on each element of the
array. Ultimately what I'd like to do is test that there are
particular values in particular array elements, and I need these
represented as strings to do that. I think.
-Chris
to_s is not generated in SOAP::Mapping::Object in a way you would like
to use it unfortunately. However to test the particular elements and their
properties just try accessing them, the accessor should have been generated.
for example, for a service that returns array (assumes 'test/unit' has
been required) :
svc.returnsArray().each { |elem| assert(elem.name == 'expectedname') }
emil
For earlier discussions is looked a though these responses were
supposed to get mapped back into the objects from the wsdl but then
there were some issues and then I'm not sure...
Been searching for 3 days now and all my hair is gone trying to get
even a simple connection working. Now that I'm connected and can send
requests I'm not sure what I'm supposed to do with the responses. Has
anyone found some documents on how to deal with the responses?
Thanks
I do find that my server is returning message objects in a very odd
form, so for now I'm doing my asserts against the returned object
subjected to #inspect, for example:
assert_match(/FooBar="foobar1"/,query1.inspect)
and that's good enough for me, for now.
The #inspect method is what "pp" uses when showing what's in the
object.
Hope that helps...
-Chris
> I do find that my server is returning message objects in a very odd
> form, so for now I'm doing my asserts against the returned object
> subjected to #inspect, for example:
>
> assert_match(/FooBar="foobar1"/,query1.inspect)
>
> and that's good enough for me, for now.
Whatever floats your boat. It was just a suggestion to use the interface
in the intended way.
SOAP::Mapping::Object is always returned on success calls, and it will
respond to the properties that are defined in the message.
cheers,
emil
:)
>SOAP::Mapping::Object is always returned on success calls, and it will
>respond to the properties that are defined in the message.
I don't think my message actually has real properties. I can't figure
out what those "{}"s are doing there. How would you address these?
For instance, assign "Name" to a variable "x"?
#<SOAP::Mapping::Object:0x2b0bfb8 {}MemberID=1 {}Name="foo1"
{}Address="bar1">
(and thanks again!)
-Chris
The properties in the result represent the message elements and
are read only. The operation result is the structure (or array of structures)
and the structure correspond to the service message response defined
in wsdl.
Try something like this:
result = service.invoke(....) # I don't have your operation name handy.
Then try accessing: result.name or result.memberID or result.address
If it is the array then iterate, and access the properties on the array
element.
The '{}' is the namespace property of each element.
cheers,
emil
####################
@result = @soap.selectStuff('Name=foo1')
@result.each do |result_obj|
puts result_obj.inspect
end
yields:
#<SOAP::Mapping::Object:0x2b02700 {}ID=5158 {}Name="foo1"
{}Address="16">
#<SOAP::Mapping::Object:0x2b01e84 {}ID=5160 {}Name="foo1"
{}Address="18">
#<SOAP::Mapping::Object:0x2b01608 {}ID=5161 {}Name="foo1"
{}lAddress="19">
#<SOAP::Mapping::Object:0x2b00d8c {}ID=5162 {}Name="foo1"
{}Address="20">
################
@result.each do |result_obj|
puts result_obj.Name
end
yields:
NoMethodError: undefined method `Name' for
#<SOAP::Mapping::Object:0x5618c18>
####################################
@result.each do |result_obj|
result_obj.each do |element|
puts element
end
end
yields:
NoMethodError: undefined method `each' for
#<SOAP::Mapping::Object:0x5618450>
##################################
You see the problem. Those objects returned don't seem to be arrays,
even though they do consist of 3 elements.
-Chris
Try modifying this
> @result.each do |result_obj|
> puts result_obj.Name
> end
>
to lowercase, such as this. This is
@result.each do |result_obj|
puts result_obj.name
end
The second snippet iteration iterates over array of arrays, and from
what we see so far it is an array of structures.
emil
eh. same result:
NoMethodError: undefined method `name' for
#<SOAP::Mapping::Object:0x5618c00>
I see, you have some other problems then. The intended
way is be able to access the properties that represent the
message parts. Your wsdl probably shows what is the
problem. Could you post it?
emil
This worked for me :
-----------------------------
....
svc = SOAP::WSDLDriverFactory.new(SERVICE_WSDL).create_rpc_driver
#svc.wiredump_dev = STDOUT
svc.selectSimpleMembers('domain=acme.org').each { |m|
p m.memberID, m.listName, m.emailAddress
}
----------------------------
The server returns sample array ArrayOfSimpleMemebersStruct.
emil
value = "#{response.element}"
It does the same thing as response.element.to_s but eval's the method
call rather than calling the class' to_s method. I'm using this in my
glue between the api client and the app to convert the values I want to
use from the response to something I can use as real values.
Another thing I learned that some might find useful is that when using
rails sessions you need to make sure you don't include ANY of the
wsdl2ruby generated driver stuff in your session:
class Foo
def initialize
@api = wsdl_driver.new
end
end
...
session[:bar] = Foo.new
is bad and nets you a couple of "singleton can't be dumped" errors at
best. You can't serialize any of the wsdl2ruby generated code. Think of
your driver as an IO object and you'll save hair.
Yep, this is a standard Ruby marshaling limitation. However there *is* a
way (although, may qualify as a grotesque hack) :)
In my RoR applications I use before / after filters to deserialise /
serialise the
session object to / from gzipped yaml format to overcome that problem. This
way I'm not required to create separate classes to deal with this issue.
The controller that needs to deal with non serializable objects extends
the below controller. That controllers offers methods for selecting which
session objects to apply the yaml / gzip. In the actual controller body
I simply mark those session objects to be treated that way :
gzip_session [:user, :cart]
class GzipSession < ActionController::Base
include ZlibMarshal
class << self
def session_objects
@session_objects ||= []
end
def gzip_session(sym)
a = sym.kind_of?(Array) ? sym : [sym]
a.each {|e| session_objects << e.to_sym }
logger.debug("Requested compress session objects: #{session_objects}")
end
end
def session_passivate
self.class.session_objects.each {|s|
if @session[s]
logger.debug("Gzip compress session: #{@session[s]}")
@session[s] = gz_dump(@session[s])
end
}
end
def session_activate
self.class.session_objects.each {|s|
if @session[s]
@session[s] = gz_load(@session[s])
logger.debug("Gzip decompressed session: #{@session[s]}")
end
}
end
end
# and here is the zlib / yaml module
module ZlibMarshal
def gz_dump(o)
zipper = Zlib::Deflate.new
zipped = zipper.deflate(YAML::dump(o), Zlib::FINISH)
zipper.close
zipped
end
def gz_load(o)
unzipper = Zlib::Inflate.new
unzipped = unzipper.inflate(o)
unzipper.close
YAML::load(unzipped)
end
end
Funny thay you mentioned that, we've been discussing this at the rails
wiki page recently:
http://wiki.rubyonrails.org/rails/pages/HowtoAvoidSessionRestoreError
cheers,
emil