aboutsummaryrefslogtreecommitdiffstats
path: root/actionwebservice/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionwebservice/lib')
-rw-r--r--actionwebservice/lib/action_web_service/client/soap_client.rb16
-rw-r--r--actionwebservice/lib/action_web_service/client/xmlrpc_client.rb4
-rw-r--r--actionwebservice/lib/action_web_service/dispatcher/abstract.rb51
-rw-r--r--actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb67
-rw-r--r--actionwebservice/lib/action_web_service/protocol/abstract.rb6
-rw-r--r--actionwebservice/lib/action_web_service/protocol/discovery.rb10
-rw-r--r--actionwebservice/lib/action_web_service/protocol/soap_protocol.rb14
-rw-r--r--actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb10
-rw-r--r--actionwebservice/lib/action_web_service/struct.rb3
-rw-r--r--actionwebservice/lib/action_web_service/vendor/ws/marshaling/soap_marshaling.rb81
-rw-r--r--actionwebservice/lib/action_web_service/vendor/ws/types.rb2
11 files changed, 178 insertions, 86 deletions
diff --git a/actionwebservice/lib/action_web_service/client/soap_client.rb b/actionwebservice/lib/action_web_service/client/soap_client.rb
index b93f6475d9..d3975d89a2 100644
--- a/actionwebservice/lib/action_web_service/client/soap_client.rb
+++ b/actionwebservice/lib/action_web_service/client/soap_client.rb
@@ -24,14 +24,16 @@ module ActionWebService # :nodoc:
# will be sent with HTTP POST.
#
# Valid options:
- # [<tt>:service_name</tt>] If the remote server has used a custom +wsdl_service_name+
- # option, you must specify it here
+ # [<tt>:type_namespace</tt>] If the remote server has used a custom namespace to
+ # declare its custom types, you can specify it here
+ # [<tt>:method_namespace</tt>] If the remote server has used a custom namespace to
+ # declare its methods, you can specify it here
def initialize(api, endpoint_uri, options={})
super(api, endpoint_uri)
- @service_name = options[:service_name]
- @namespace = @service_name ? '' : "urn:#{@service_name}"
- @marshaler = WS::Marshaling::SoapMarshaler.new
- @encoder = WS::Encoding::SoapRpcEncoding.new
+ @type_namespace = options[:type_namespace] || 'urn:ActionWebService'
+ @method_namespace = options[:method_namespace] || 'urn:ActionWebService'
+ @marshaler = WS::Marshaling::SoapMarshaler.new @type_namespace
+ @encoder = WS::Encoding::SoapRpcEncoding.new @method_namespace
@soap_action_base = options[:soap_action_base]
@soap_action_base ||= URI.parse(endpoint_uri).path
@driver = create_soap_rpc_driver(api, endpoint_uri)
@@ -53,7 +55,7 @@ module ActionWebService # :nodoc:
driver.mapping_registry = @marshaler.registry
api.api_methods.each do |name, info|
public_name = api.public_api_method_name(name)
- qname = XSD::QName.new(@namespace, public_name)
+ qname = XSD::QName.new(@method_namespace, public_name)
action = soap_action(public_name)
expects = info[:expects]
returns = info[:returns]
diff --git a/actionwebservice/lib/action_web_service/client/xmlrpc_client.rb b/actionwebservice/lib/action_web_service/client/xmlrpc_client.rb
index dc7ad1517f..27fe537404 100644
--- a/actionwebservice/lib/action_web_service/client/xmlrpc_client.rb
+++ b/actionwebservice/lib/action_web_service/client/xmlrpc_client.rb
@@ -56,7 +56,7 @@ module ActionWebService # :nodoc:
i = 0
expects.each do |spec|
type_binding = @marshaler.register_type(spec)
- info = WS::ParamInfo.create(spec, i, type_binding)
+ info = WS::ParamInfo.create(spec, type_binding, i)
params[i] = @marshaler.marshal(WS::Param.new(params[i], info))
i += 1
end
@@ -68,7 +68,7 @@ module ActionWebService # :nodoc:
info = @api.api_methods[method_name.to_sym]
return true unless returns = info[:returns]
type_binding = @marshaler.register_type(returns[0])
- info = WS::ParamInfo.create(returns[0], 0, type_binding)
+ info = WS::ParamInfo.create(returns[0], type_binding, 0)
info.name = 'return'
@marshaler.transform_inbound(WS::Param.new(return_value, info))
end
diff --git a/actionwebservice/lib/action_web_service/dispatcher/abstract.rb b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
index b7560afc87..641f291533 100644
--- a/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
+++ b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
@@ -19,7 +19,7 @@ module ActionWebService # :nodoc:
case web_service_dispatching_mode
when :direct
web_service_direct_invoke(invocation)
- when :delegated
+ when :delegated, :layered
web_service_delegated_invoke(invocation)
end
end
@@ -27,7 +27,11 @@ module ActionWebService # :nodoc:
def web_service_direct_invoke(invocation)
@method_params = invocation.method_ordered_params
return_value = self.__send__(invocation.api_method_name)
- returns = invocation.returns ? invocation.returns[0] : nil
+ if invocation.api.has_api_method?(invocation.api_method_name)
+ returns = invocation.returns ? invocation.returns[0] : nil
+ else
+ returns = return_value.class
+ end
invocation.protocol.marshal_response(invocation.public_method_name, return_value, returns)
end
@@ -44,29 +48,43 @@ module ActionWebService # :nodoc:
end
def web_service_invocation(request)
+ public_method_name = request.method_name
invocation = Invocation.new
invocation.protocol = request.protocol
invocation.service_name = request.service_name
+ if web_service_dispatching_mode == :layered
+ if request.method_name =~ /^([^\.]+)\.(.*)$/
+ public_method_name = $2
+ invocation.service_name = $1
+ end
+ end
+ invocation.public_method_name = public_method_name
case web_service_dispatching_mode
when :direct
invocation.api = self.class.web_service_api
invocation.service = self
- when :delegated
- invocation.service = web_service_object(request.service_name) rescue nil
+ when :delegated, :layered
+ invocation.service = web_service_object(invocation.service_name) rescue nil
unless invocation.service
- raise(DispatcherError, "failed to instantiate service #{invocation.service_name}")
+ raise(DispatcherError, "service #{invocation.service_name} not available")
end
invocation.api = invocation.service.class.web_service_api
end
- public_method_name = request.method_name
- unless invocation.api.has_public_api_method?(public_method_name)
- raise(DispatcherError, "no such method '#{public_method_name}' on API #{invocation.api}")
+ if invocation.api.has_public_api_method?(public_method_name)
+ invocation.api_method_name = invocation.api.api_method_name(public_method_name)
+ else
+ if invocation.api.default_api_method.nil?
+ raise(DispatcherError, "no such method '#{public_method_name}' on API #{invocation.api}")
+ else
+ invocation.api_method_name = invocation.api.default_api_method.to_s.to_sym
+ end
+ end
+ unless invocation.service.respond_to?(invocation.api_method_name)
+ raise(DispatcherError, "no such method '#{public_method_name}' on API #{invocation.api} (#{invocation.api_method_name})")
end
- invocation.public_method_name = public_method_name
- invocation.api_method_name = invocation.api.api_method_name(public_method_name)
info = invocation.api.api_methods[invocation.api_method_name]
- invocation.expects = info[:expects]
- invocation.returns = info[:returns]
+ invocation.expects = info ? info[:expects] : nil
+ invocation.returns = info ? info[:returns] : nil
if invocation.expects
i = 0
invocation.method_ordered_params = request.method_params.map do |param|
@@ -83,7 +101,7 @@ module ActionWebService # :nodoc:
params = []
invocation.expects.each do |spec|
type_binding = invocation.protocol.register_signature_type(spec)
- info = WS::ParamInfo.create(spec, i, type_binding)
+ info = WS::ParamInfo.create(spec, type_binding, i)
params << WS::Param.new(invocation.method_ordered_params[i], info)
i += 1
end
@@ -96,10 +114,15 @@ module ActionWebService # :nodoc:
invocation.method_ordered_params = []
invocation.method_named_params = {}
end
+ if invocation.returns
+ invocation.returns.each do |spec|
+ invocation.protocol.register_signature_type(spec)
+ end
+ end
invocation
end
- class Invocation
+ class Invocation # :nodoc:
attr_accessor :protocol
attr_accessor :service_name
attr_accessor :api
diff --git a/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb b/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb
index a35029b40d..7080f813d4 100644
--- a/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb
+++ b/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb
@@ -20,20 +20,22 @@ module ActionWebService # :nodoc:
base.add_web_service_definition_callback do |klass, name, info|
if klass.web_service_dispatching_mode == :delegated
klass.class_eval "def #{name}; dispatch_web_service_request; end"
+ elsif klass.web_service_dispatching_mode == :layered
+ klass.class_eval 'def api; dispatch_web_service_request; end'
end
end
base.extend(ClassMethods)
base.send(:include, ActionWebService::Dispatcher::ActionController::InstanceMethods)
end
- module ClassMethods
+ module ClassMethods # :nodoc:
def inherited(child)
inherited_without_action_controller(child)
child.send(:include, ActionWebService::Dispatcher::ActionController::WsdlAction)
end
end
- module InstanceMethods
+ module InstanceMethods # :nodoc:
private
def dispatch_web_service_request
request = discover_web_service_request(@request)
@@ -105,16 +107,16 @@ module ActionWebService # :nodoc:
def log_request(request, body)
unless logger.nil?
name = request.method_name
- params = request.method_params.map{|x| x.value.inspect}
+ params = request.method_params.map{|x| "#{x.info.name}=>#{x.value.inspect}"}
service = request.service_name
- logger.debug("\nWeb Service Request: #{name}(#{params}) #{service}")
+ logger.debug("\nWeb Service Request: #{name}(#{params.join(", ")}) Entrypoint: #{service}")
logger.debug(indent(body))
end
end
def log_response(response, elapsed=nil)
unless logger.nil?
- logger.debug("\nWeb Service Response (%f):" + (elapsed ? " (%f):" % elapsed : ":"))
+ logger.debug("\nWeb Service Response" + (elapsed ? " (%f):" % elapsed : ":"))
logger.debug(indent(response.body))
end
end
@@ -124,7 +126,7 @@ module ActionWebService # :nodoc:
end
end
- module WsdlAction
+ module WsdlAction # :nodoc:
XsdNs = 'http://www.w3.org/2001/XMLSchema'
WsdlNs = 'http://schemas.xmlsoap.org/wsdl/'
SoapNs = 'http://schemas.xmlsoap.org/wsdl/soap/'
@@ -155,7 +157,7 @@ module ActionWebService # :nodoc:
xml = ''
dispatching_mode = web_service_dispatching_mode
global_service_name = wsdl_service_name
- namespace = "urn:#{global_service_name}"
+ namespace = 'urn:ActionWebService'
soap_action_base = "/#{controller_name}"
marshaler = WS::Marshaling::SoapMarshaler.new(namespace)
@@ -164,18 +166,18 @@ module ActionWebService # :nodoc:
when :direct
api = self.class.web_service_api
web_service_name = controller_class_name.sub(/Controller$/, '').underscore
- apis[web_service_name] = [api, register_api(marshaler, api)]
+ apis[web_service_name] = [api, register_api(api, marshaler)]
when :delegated
self.class.web_services.each do |web_service_name, info|
service = web_service_object(web_service_name)
api = service.class.web_service_api
- apis[web_service_name] = [api, register_api(marshaler, api)]
+ apis[web_service_name] = [api, register_api(api, marshaler)]
end
end
custom_types = []
apis.values.each do |api, bindings|
bindings.each do |b|
- custom_types << b if b.is_custom_type?
+ custom_types << b
end
end
@@ -200,15 +202,16 @@ module ActionWebService # :nodoc:
xm.xsd(:complexContent) do
xm.xsd(:restriction, 'base' => 'soapenc:Array') do
xm.xsd(:attribute, 'ref' => 'soapenc:arrayType',
- 'wsdl:arrayType' => binding.element_binding.qualified_type_name + '[]')
+ 'wsdl:arrayType' => binding.element_binding.qualified_type_name('typens') + '[]')
end
end
end
when binding.is_typed_struct?
xm.xsd(:complexType, 'name' => binding.type_name) do
xm.xsd(:all) do
- binding.each_member do |name, type_name|
- xm.xsd(:element, 'name' => name, 'type' => type_name)
+ binding.each_member do |name, spec|
+ b = marshaler.register_type(spec)
+ xm.xsd(:element, 'name' => name, 'type' => b.qualified_type_name('typens'))
end
end
end
@@ -229,7 +232,7 @@ module ActionWebService # :nodoc:
returns = info[:returns]
if returns
binding = marshaler.register_type(returns[0])
- xm.part('name' => 'return', 'type' => binding.qualified_type_name)
+ xm.part('name' => 'return', 'type' => binding.qualified_type_name('typens'))
end
else
expects = info[:expects]
@@ -242,7 +245,7 @@ module ActionWebService # :nodoc:
param_name = "param#{i}"
end
binding = marshaler.register_type(type)
- xm.part('name' => param_name, 'type' => binding.qualified_type_name)
+ xm.part('name' => param_name, 'type' => binding.qualified_type_name('typens'))
i += 1
end if expects
end
@@ -273,7 +276,7 @@ module ActionWebService # :nodoc:
public_name = api.public_api_method_name(name)
xm.operation('name' => public_name) do
case web_service_dispatching_mode
- when :direct
+ when :direct, :layered
soap_action = soap_action_base + "/api/" + public_name
when :delegated
soap_action = soap_action_base \
@@ -325,20 +328,34 @@ module ActionWebService # :nodoc:
"#{global_service}#{service.to_s.camelize}Binding"
end
- def register_api(marshaler, api)
- type_bindings = []
+ def register_api(api, marshaler)
+ bindings = {}
+ traverse_custom_types(api, marshaler) do |binding|
+ bindings[binding] = nil unless bindings.has_key?(binding.type_class)
+ end
+ bindings.keys
+ end
+
+ def traverse_custom_types(api, marshaler, &block)
api.api_methods.each do |name, info|
expects, returns = info[:expects], info[:returns]
- if expects
- expects.each{|type| type_bindings << marshaler.register_type(type)}
- end
- if returns
- returns.each{|type| type_bindings << marshaler.register_type(type)}
+ expects.each{|x| traverse_custom_type_spec(marshaler, x, &block)} if expects
+ returns.each{|x| traverse_custom_type_spec(marshaler, x, &block)} if returns
+ end
+ end
+
+ def traverse_custom_type_spec(marshaler, spec, &block)
+ binding = marshaler.register_type(spec)
+ if binding.is_typed_struct?
+ binding.each_member do |name, member_spec|
+ traverse_custom_type_spec(marshaler, member_spec, &block)
end
+ elsif binding.is_typed_array?
+ traverse_custom_type_spec(marshaler, binding.element_binding.type_class, &block)
end
- type_bindings
+ yield binding
end
- end
+ end
end
end
end
diff --git a/actionwebservice/lib/action_web_service/protocol/abstract.rb b/actionwebservice/lib/action_web_service/protocol/abstract.rb
index f628fc4aee..7526539d53 100644
--- a/actionwebservice/lib/action_web_service/protocol/abstract.rb
+++ b/actionwebservice/lib/action_web_service/protocol/abstract.rb
@@ -1,9 +1,9 @@
module ActionWebService # :nodoc:
module Protocol # :nodoc:
- class ProtocolError < ActionWebService::ActionWebServiceError
+ class ProtocolError < ActionWebServiceError # :nodoc:
end
- class Request
+ class Request # :nodoc:
attr :protocol
attr :method_name
attr :method_params
@@ -17,7 +17,7 @@ module ActionWebService # :nodoc:
end
end
- class Response
+ class Response # :nodoc:
attr :body
attr :content_type
diff --git a/actionwebservice/lib/action_web_service/protocol/discovery.rb b/actionwebservice/lib/action_web_service/protocol/discovery.rb
index ab51958ed9..40875975bf 100644
--- a/actionwebservice/lib/action_web_service/protocol/discovery.rb
+++ b/actionwebservice/lib/action_web_service/protocol/discovery.rb
@@ -1,18 +1,18 @@
-module ActionWebService
- module Protocol
- module Discovery
+module ActionWebService # :nodoc:
+ module Protocol # :nodoc:
+ module Discovery # :nodoc:
def self.included(base)
base.extend(ClassMethods)
base.send(:include, ActionWebService::Protocol::Discovery::InstanceMethods)
end
- module ClassMethods
+ module ClassMethods # :nodoc:
def register_protocol(klass)
write_inheritable_array("web_service_protocols", [klass])
end
end
- module InstanceMethods
+ module InstanceMethods # :nodoc:
private
def discover_web_service_request(ap_request)
(self.class.read_inheritable_attribute("web_service_protocols") || []).each do |protocol|
diff --git a/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb b/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb
index f2e761f431..6e3df54b00 100644
--- a/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb
+++ b/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb
@@ -1,15 +1,15 @@
-module ActionWebService
- module Protocol
- module Soap
+module ActionWebService # :nodoc:
+ module Protocol # :nodoc:
+ module Soap # :nodoc:
def self.included(base)
base.register_protocol(SoapProtocol)
base.class_inheritable_option(:wsdl_service_name)
end
- class SoapProtocol
+ class SoapProtocol # :nodoc:
def initialize
- @encoder = WS::Encoding::SoapRpcEncoding.new
- @marshaler = WS::Marshaling::SoapMarshaler.new
+ @encoder = WS::Encoding::SoapRpcEncoding.new 'urn:ActionWebService'
+ @marshaler = WS::Marshaling::SoapMarshaler.new 'urn:ActionWebService'
end
def unmarshal_request(ap_request)
@@ -23,7 +23,7 @@ module ActionWebService
def marshal_response(method_name, return_value, signature_type)
if !return_value.nil? && signature_type
type_binding = @marshaler.register_type(signature_type)
- info = WS::ParamInfo.create(signature_type, 0, type_binding)
+ info = WS::ParamInfo.create(signature_type, type_binding, 0)
return_value = @marshaler.marshal(WS::Param.new(return_value, info))
else
return_value = nil
diff --git a/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb b/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb
index 1533a2bdb9..8d6af246ec 100644
--- a/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb
+++ b/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb
@@ -1,11 +1,11 @@
-module ActionWebService
- module Protocol
- module XmlRpc
+module ActionWebService # :nodoc:
+ module Protocol # :nodoc:
+ module XmlRpc # :nodoc:
def self.included(base)
base.register_protocol(XmlRpcProtocol)
end
- class XmlRpcProtocol
+ class XmlRpcProtocol # :nodoc:
attr :marshaler
def initialize
@@ -25,7 +25,7 @@ module ActionWebService
def marshal_response(method_name, return_value, signature_type)
if !return_value.nil? && signature_type
type_binding = @marshaler.register_type(signature_type)
- info = WS::ParamInfo.create(signature_type, 0, type_binding)
+ info = WS::ParamInfo.create(signature_type, type_binding, 0)
return_value = @marshaler.marshal(WS::Param.new(return_value, info))
else
return_value = nil
diff --git a/actionwebservice/lib/action_web_service/struct.rb b/actionwebservice/lib/action_web_service/struct.rb
index 77f4fbf4aa..d4e2ba9ce6 100644
--- a/actionwebservice/lib/action_web_service/struct.rb
+++ b/actionwebservice/lib/action_web_service/struct.rb
@@ -17,8 +17,7 @@ module ActionWebService
# person = Person.new(:id => 5, :firstname => 'john', :lastname => 'doe')
#
# Active Record model classes are already implicitly supported for method
- # return signatures. A structure containing its columns as members will be
- # automatically generated if its present in a signature.
+ # return signatures.
class Struct
# If a Hash is given as argument to an ActionWebService::Struct constructor,
diff --git a/actionwebservice/lib/action_web_service/vendor/ws/marshaling/soap_marshaling.rb b/actionwebservice/lib/action_web_service/vendor/ws/marshaling/soap_marshaling.rb
index 99e2a7ff28..3032639510 100644
--- a/actionwebservice/lib/action_web_service/vendor/ws/marshaling/soap_marshaling.rb
+++ b/actionwebservice/lib/action_web_service/vendor/ws/marshaling/soap_marshaling.rb
@@ -19,13 +19,7 @@ module WS
end
def marshal(param)
- if param.info.type.is_a?(Array)
- (class << param.value; self; end).class_eval do
- define_method(:arytype) do
- param.info.data.qname
- end
- end
- end
+ annotate_arrays(param.info.data, param.value)
if param.value.is_a?(Exception)
detail = SOAP::Mapping::SOAPException.new(param.value)
soap_obj = SOAP::SOAPFault.new(
@@ -48,9 +42,9 @@ module WS
param.info.type = value.class
mapping = @registry.find_mapped_soap_class(param.info.type) rescue nil
if soap_type && soap_type.name == 'Array' && soap_type.namespace == SoapEncodingNS
- param.info.data = SoapBinding.new(soap_object.arytype, mapping)
+ param.info.data = SoapBinding.new(self, soap_object.arytype, Array, mapping)
else
- param.info.data = SoapBinding.new(soap_type, mapping)
+ param.info.data = SoapBinding.new(self, soap_type, value.class, mapping)
end
param
end
@@ -71,7 +65,7 @@ module WS
if (mapping = @registry.find_mapped_soap_class(type_class) rescue nil)
qname = mapping[2] ? mapping[2][:type] : nil
qname ||= soap_base_type_name(mapping[0])
- type_binding = SoapBinding.new(qname, mapping)
+ type_binding = SoapBinding.new(self, qname, type_class, mapping)
else
qname = XSD::QName.new(@type_namespace, soap_type_name(type_class.name))
@registry.add(type_class,
@@ -79,7 +73,7 @@ module WS
typed_struct_factory(type_class),
{ :type => qname })
mapping = @registry.find_mapped_soap_class(type_class)
- type_binding = SoapBinding.new(qname, mapping)
+ type_binding = SoapBinding.new(self, qname, type_class, mapping)
end
array_binding = nil
@@ -92,13 +86,43 @@ module WS
array_mapping = @registry.find_mapped_soap_class(Array)
end
qname = XSD::QName.new(@type_namespace, soap_type_name(type_class.name) + 'Array')
- array_binding = SoapBinding.new(qname, array_mapping, type_binding)
+ array_binding = SoapBinding.new(self, qname, Array, array_mapping, type_binding)
end
@spec2binding[spec] = array_binding ? array_binding : type_binding
+ @spec2binding[spec]
end
protected
+ def annotate_arrays(binding, value)
+ if binding.is_typed_array?
+ mark_typed_array(value, binding.element_binding.qname)
+ if binding.element_binding.is_custom_type?
+ value.each do |element|
+ annotate_arrays(register_type(element.class), element)
+ end
+ end
+ elsif binding.is_typed_struct?
+ if binding.type_class.respond_to?(:members)
+ binding.type_class.members.each do |name, spec|
+ member_binding = register_type(spec)
+ member_value = value.send(name)
+ if member_binding.is_custom_type?
+ annotate_arrays(member_binding, member_value)
+ end
+ end
+ end
+ end
+ end
+
+ def mark_typed_array(array, qname)
+ (class << array; self; end).class_eval do
+ define_method(:arytype) do
+ qname
+ end
+ end
+ end
+
def typed_struct_factory(type_class)
if Object.const_defined?('ActiveRecord')
if WS.derived_from?(ActiveRecord::Base, type_class)
@@ -132,11 +156,14 @@ module WS
class SoapBinding
attr :qname
+ attr :type_class
attr :mapping
attr :element_binding
- def initialize(qname, mapping, element_binding=nil)
+ def initialize(marshaler, qname, type_class, mapping, element_binding=nil)
+ @marshaler = marshaler
@qname = qname
+ @type_class = type_class
@mapping = mapping
@element_binding = element_binding
end
@@ -155,8 +182,18 @@ module WS
end
def each_member(&block)
- unless is_typed_struct?
- raise(SoapError, "not a structured type")
+ if is_typed_struct?
+ if @mapping[1] == SOAP::Mapping::Registry::TypedStructFactory
+ if @type_class.respond_to?(:members)
+ @type_class.members.each do |name, spec|
+ yield name, spec
+ end
+ end
+ elsif @mapping[1].is_a?(WS::Marshaling::SoapActiveRecordStructFactory)
+ @type_class.columns.each do |column|
+ yield column.name, column.klass
+ end
+ end
end
end
@@ -220,5 +257,19 @@ module WS
return false
end
end
+
+ module ActiveRecordSoapMarshallable
+ def allocate
+ obj = super
+ attrs = {}
+ self.columns.each{|c| attrs[c.name.to_s] = c.default}
+ obj.instance_variable_set('@attributes', attrs)
+ obj
+ end
+ end
+
+ if Object.const_defined?('ActiveRecord')
+ ActiveRecord::Base.extend(ActiveRecordSoapMarshallable)
+ end
end
end
diff --git a/actionwebservice/lib/action_web_service/vendor/ws/types.rb b/actionwebservice/lib/action_web_service/vendor/ws/types.rb
index 24b96dc327..650cdb0848 100644
--- a/actionwebservice/lib/action_web_service/vendor/ws/types.rb
+++ b/actionwebservice/lib/action_web_service/vendor/ws/types.rb
@@ -105,7 +105,7 @@ module WS
@data = data
end
- def self.create(spec, index=nil, data=nil)
+ def self.create(spec, data, index=nil)
name = spec.is_a?(Hash) ? spec.keys[0].to_s : (index ? "param#{index}" : nil)
type = BaseTypes.canonical_param_type_class(spec)
ParamInfo.new(name, type, data)