Skip to content

Commit

Permalink
Make response grabber more consistent and bulletproof when it comes t…
Browse files Browse the repository at this point in the history
…o missing fields (#105, fixes #106)
  • Loading branch information
inossidabile committed Aug 18, 2013
1 parent 89bdeba commit 2935132
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 23 deletions.
46 changes: 25 additions & 21 deletions lib/wash_out/dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,36 +104,40 @@ def _render_soap(result, options)

inject = lambda {|data, map|
result_spec = []
return result_spec if data.nil?

map.each_with_index do |param, i|
result_spec[i] = param.flat_copy

# Inline complex structure
if param.struct? && !param.multiplied
result_spec[i].map = inject.call(data[param.raw_name], param.map)
unless data.is_a?(Hash)
raise ProgrammerError,
"SOAP response used #{data.inspect} (which is #{data.class.name}), " +
"in the context where a Hash with key of '#{param.raw_name}' " +
"was expected."
end

# Inline array of complex structures
elsif param.struct? && param.multiplied
if data.nil?
data = {} # when no data is given
elsif data.is_a?(Array)
raise ProgrammerError,
"SOAP response used #{data.inspect} (which is an Array), " +
"in the context where a Hash with key of '#{param.raw_name}' " +
"was expected."
end
data[param.raw_name] = [] unless data[param.raw_name].is_a?(Array)
result_spec[i].map = data[param.raw_name].map{|e| inject.call(e, param.map)}
value = data[param.raw_name]

else
val = data[param.raw_name]
if param.multiplied and val and not val.is_a?(Array)
unless value.nil?
if param.multiplied && !value.is_a?(Array)
raise ProgrammerError,
"SOAP response tried to use '#{val.inspect}' " +
"(which is of type #{val.class}), as the value for " +
"SOAP response tried to use '#{value.inspect}' " +
"(which is of type #{value.class.name}), as the value for " +
"'#{param.raw_name}' (which expects an Array)."
end
result_spec[i].value = val

# Inline complex structure {:foo => {bar: ...}}
if param.struct? && !param.multiplied
result_spec[i].map = inject.call(value, param.map)

# Inline array of complex structures {:foo => [{bar: ...}]}
elsif param.struct? && param.multiplied
result_spec[i].map = value.map{|e| inject.call(e, param.map)}

# Inline scalar {:foo => :string}
else
result_spec[i].value = value
end
end
end

Expand Down
16 changes: 14 additions & 2 deletions spec/lib/wash_out_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ def rocknroll
it "respond with complext definition" do
mock_controller do
soap_action "rocknroll",
:args => nil, :return => { :my_value => [{ :value => :integer}] }
:args => nil, :return => { :my_value => [{ :value => :integer }] }
def rocknroll
render :soap => {}
end
Expand All @@ -366,7 +366,7 @@ def rocknroll
it "respond with nested simple definition" do
mock_controller do
soap_action "rocknroll",
:args => nil, :return => { :my_value => { :my_array => [{ :value => :integer}] } }
:args => nil, :return => { :my_value => { :my_array => [{ :value => :integer }] } }
def rocknroll
render :soap => {}
end
Expand All @@ -375,6 +375,18 @@ def rocknroll
savon(:rocknroll)[:rocknroll_response][:my_value].
should == { :"@xsi:type" => "tns:MyValue" }
end

it "handles incomplete array response" do
mock_controller do
soap_action "rocknroll",
:args => nil, :return => { :my_value => [{ :value => :string }] }
def rocknroll
render :soap => { :my_value => [nil] }
end
end

expect{savon(:rocknroll)}.not_to raise_error
end
end
end

Expand Down

0 comments on commit 2935132

Please sign in to comment.