Skip to content

Commit

Permalink
* Fix casting of nested members in structured types if we have a sig…
Browse files Browse the repository at this point in the history
…nature

   type available for it even if they are already of the desired type as
   SOAP/XML-RPC unmarshaling may have gotten it wrong: SOAP likes to always
   use DateTime no matter what, for example, whereas we allow a distinction
   between Date, DateTime and Time in the signature for convenience casting
 * Fix raising of exceptions by test_invoke so functional tests fail properly on exception
   instead of returning the exception object
 * Fix Struct#each_pair to yield the value and not the member type


git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1089 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
leonbreedt committed Apr 4, 2005
1 parent a87c1d4 commit d7a7d85
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 16 deletions.
3 changes: 3 additions & 0 deletions actionwebservice/CHANGELOG
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@


* Include backtraces in 500 error responses for failed request parsing, and remove "rescue nil" statements obscuring real errors for XML-RPC * Include backtraces in 500 error responses for failed request parsing, and remove "rescue nil" statements obscuring real errors for XML-RPC


* Perform casting of struct members even if the structure is already of the correct type, so that the type we specify for
the struct member is always the type of the value seen by the API implementation



*0.6.2* (27th March, 2005) *0.6.2* (27th March, 2005)


Expand Down
13 changes: 10 additions & 3 deletions actionwebservice/lib/action_web_service/casting.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def cast_returns(api_method, return_value) # :nodoc:


def cast(value, signature_type) # :nodoc: def cast(value, signature_type) # :nodoc:
return value if signature_type.nil? # signature.length != params.length return value if signature_type.nil? # signature.length != params.length
unless signature_type.array? unless signature_type.array? || signature_type.structured?
return value if canonical_type(value.class) == signature_type.type return value if canonical_type(value.class) == signature_type.type
end end
if signature_type.array? if signature_type.array?
Expand Down Expand Up @@ -86,13 +86,20 @@ def cast_base_type(value, signature_type) # :nodoc:
end end


def cast_to_structured_type(value, signature_type) # :nodoc: def cast_to_structured_type(value, signature_type) # :nodoc:
obj = signature_type.type_class.new obj = nil
obj = value if canonical_type(value.class) == canonical_type(signature_type.type)
obj ||= signature_type.type_class.new
if value.respond_to?(:each_pair) if value.respond_to?(:each_pair)
klass = signature_type.type_class klass = signature_type.type_class
value.each_pair do |name, val| value.each_pair do |name, val|
type = klass.respond_to?(:member_type) ? klass.member_type(name) : nil type = klass.respond_to?(:member_type) ? klass.member_type(name) : nil
val = cast(val, type) if type val = cast(val, type) if type
obj.send("#{name}=", val) obj.__send__("#{name}=", val)
end
elsif value.respond_to?(:attributes)
signature_type.each_member do |name, type|
val = value.__send__(name)
obj.__send__("#{name}=", cast(val, type))
end end
else else
raise CastingError, "Don't know how to cast #{value.class} to #{signature_type.type_class}" raise CastingError, "Don't know how to cast #{value.class} to #{signature_type.type_class}"
Expand Down
4 changes: 2 additions & 2 deletions actionwebservice/lib/action_web_service/struct.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Struct
# it can contain initial values for the structure member. # it can contain initial values for the structure member.
def initialize(values={}) def initialize(values={})
if values.is_a?(Hash) if values.is_a?(Hash)
values.map{|k,v| send('%s=' % k.to_s, v)} values.map{|k,v| __send__('%s=' % k.to_s, v)}
end end
end end


Expand All @@ -36,7 +36,7 @@ def [](name)
# Iterates through each member # Iterates through each member
def each_pair(&block) def each_pair(&block)
self.class.members.each do |name, type| self.class.members.each do |name, type|
yield name, type yield name, self.__send__(name)
end end
end end


Expand Down
10 changes: 4 additions & 6 deletions actionwebservice/lib/action_web_service/test_invoke.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -59,10 +59,8 @@ def encode_rpc_call(service_name, api_method_name, *args)


def decode_rpc_response def decode_rpc_response
public_method_name, return_value = protocol.decode_response(@response.body) public_method_name, return_value = protocol.decode_response(@response.body)
unless @return_exceptions exception = is_exception?(return_value)
exception = is_exception?(return_value) raise exception if exception
raise exception if exception
end
return_value return_value
end end


Expand Down Expand Up @@ -90,10 +88,10 @@ def protocol


def is_exception?(obj) def is_exception?(obj)
case protocol case protocol
when :soap when :soap, ActionWebService::Protocol::Soap::SoapProtocol
(obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && \ (obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && \
obj.detail.cause.is_a?(Exception)) ? obj.detail.cause : nil obj.detail.cause.is_a?(Exception)) ? obj.detail.cause : nil
when :xmlrpc when :xmlrpc, ActionWebService::Protocol::XmlRpc::XmlRpcProtocol
obj.is_a?(XMLRPC::FaultException) ? obj : nil obj.is_a?(XMLRPC::FaultException) ? obj : nil
end end
end end
Expand Down
8 changes: 3 additions & 5 deletions actionwebservice/test/struct_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -44,11 +44,9 @@ def test_initializer_and_lookup
end end


def test_each_pair def test_each_pair
members = {} @struct.each_pair do |name, value|
@struct.each_pair do |name, type| assert_equal @struct.__send__(name), value
members[name] = type assert_equal @struct[name], value
assert ActionWebService::BaseType === type
end end
assert_equal members, Struct.members
end end
end end

0 comments on commit d7a7d85

Please sign in to comment.