diff --git a/actionwebservice/CHANGELOG b/actionwebservice/CHANGELOG index ebbb975501c5e..9f6abfdc5d137 100644 --- a/actionwebservice/CHANGELOG +++ b/actionwebservice/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Fix soap type registration of multidimensional arrays (#4232) + * Fix that marshaler couldn't handle ActiveRecord models defined in a different namespace (#2392). * Fix that marshaler couldn't handle structs with members of ActiveRecord type (#1889). diff --git a/actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb b/actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb index fa917ad4a548d..351c9da1593b6 100644 --- a/actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb +++ b/actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb @@ -40,32 +40,25 @@ def ruby_to_soap(obj) def register_type(type) return @type2binding[type] if @type2binding.has_key?(type) - type_class = type.array?? type.element_type.type_class : type.type_class - type_type = type.array?? type.element_type : type - type_binding = nil - 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(self, qname, type_type, mapping) - else - qname = XSD::QName.new(@namespace, soap_type_name(type_class.name)) - @registry.add(type_class, - SOAP::SOAPStruct, - typed_struct_factory(type_class), - { :type => qname }) - mapping = @registry.find_mapped_soap_class(type_class) - type_binding = SoapBinding.new(self, qname, type_type, mapping) - end - - array_binding = nil if type.array? array_mapping = @registry.find_mapped_soap_class(Array) qname = XSD::QName.new(@namespace, soap_type_name(type.element_type.type_class.name) + 'Array') - array_binding = SoapBinding.new(self, qname, type, array_mapping, type_binding) + element_type_binding = register_type(type.element_type) + @type2binding[type] = SoapBinding.new(self, qname, type, array_mapping, element_type_binding) + elsif (mapping = @registry.find_mapped_soap_class(type.type_class) rescue nil) + qname = mapping[2] ? mapping[2][:type] : nil + qname ||= soap_base_type_name(mapping[0]) + @type2binding[type] = SoapBinding.new(self, qname, type, mapping) + else + qname = XSD::QName.new(@namespace, soap_type_name(type.type_class.name)) + @registry.add(type.type_class, + SOAP::SOAPStruct, + typed_struct_factory(type.type_class), + { :type => qname }) + mapping = @registry.find_mapped_soap_class(type.type_class) + @type2binding[type] = SoapBinding.new(self, qname, type, mapping) end - @type2binding[type] = array_binding ? array_binding : type_binding - if type.structured? type.each_member do |m_name, m_type| register_type(m_type) diff --git a/actionwebservice/test/abstract_client.rb b/actionwebservice/test/abstract_client.rb index c5484b6b62253..5207d8ef21c88 100644 --- a/actionwebservice/test/abstract_client.rb +++ b/actionwebservice/test/abstract_client.rb @@ -34,6 +34,10 @@ class WithModel < ActionWebService::Struct member :user, User member :users, [User] end + + class WithMultiDimArray < ActionWebService::Struct + member :pref, [[:string]] + end class API < ActionWebService::API::Base api_method :void @@ -48,6 +52,7 @@ class API < ActionWebService::API::Base api_method :user_return, :returns => [User] api_method :with_model_return, :returns => [WithModel] api_method :scoped_model_return, :returns => [Accounting::User] + api_method :multi_dim_return, :returns => [WithMultiDimArray] end class NullLogOut @@ -124,6 +129,10 @@ def with_model_return def scoped_model_return Accounting::User.find(1) end + + def multi_dim_return + WithMultiDimArray.new :pref => [%w{pref1 value1}, %w{pref2 value2}] + end end class AbstractClientLet < WEBrick::HTTPServlet::AbstractServlet diff --git a/actionwebservice/test/abstract_unit.rb b/actionwebservice/test/abstract_unit.rb index 149f108c98c93..6862d222e48e4 100644 --- a/actionwebservice/test/abstract_unit.rb +++ b/actionwebservice/test/abstract_unit.rb @@ -29,3 +29,10 @@ ActiveRecord::Base.connection Test::Unit::TestCase.fixture_path = "#{File.dirname(__FILE__)}/fixtures/" + +# restore default raw_post functionality +class ActionController::TestRequest + def raw_post + super + end +end \ No newline at end of file diff --git a/actionwebservice/test/client_soap_test.rb b/actionwebservice/test/client_soap_test.rb index ee02d919a43c4..c03c24141f57d 100644 --- a/actionwebservice/test/client_soap_test.rb +++ b/actionwebservice/test/client_soap_test.rb @@ -142,4 +142,11 @@ def test_scoped_model_return assert_kind_of Accounting::User, scoped_model assert_equal 'Kent', scoped_model.name end + + def test_multi_dim_return + md_struct = @client.multi_dim_return + assert_kind_of Array, md_struct.pref + assert_equal 2, md_struct.pref.size + assert_kind_of Array, md_struct.pref[0] + end end diff --git a/actionwebservice/test/client_xmlrpc_test.rb b/actionwebservice/test/client_xmlrpc_test.rb index 8bb0fdffdcc3c..0abd5898d82d4 100644 --- a/actionwebservice/test/client_xmlrpc_test.rb +++ b/actionwebservice/test/client_xmlrpc_test.rb @@ -141,4 +141,11 @@ def test_scoped_model_return assert_kind_of Accounting::User, scoped_model assert_equal 'Kent', scoped_model.name end + + def test_multi_dim_return + md_struct = @client.multi_dim_return + assert_kind_of Array, md_struct.pref + assert_equal 2, md_struct.pref.size + assert_kind_of Array, md_struct.pref[0] + end end