From 0a12fb3e49569d00631b3a6e7093fc1e6811819c Mon Sep 17 00:00:00 2001 From: rubiii Date: Fri, 5 Nov 2010 13:43:23 +0100 Subject: [PATCH] added Savon.response_pattern (from savon_model) --- lib/savon/global.rb | 9 +++++ lib/savon/soap/response.rb | 30 ++++++++++++++- spec/savon/savon_spec.rb | 13 +++++++ spec/savon/soap/response_spec.rb | 63 +++++++++++++++++++++++++++++++- 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/lib/savon/global.rb b/lib/savon/global.rb index 5aa4765c..79b21bac 100644 --- a/lib/savon/global.rb +++ b/lib/savon/global.rb @@ -61,6 +61,14 @@ def strip_namespaces? # Sets whether to strip namespaces in a SOAP response Hash. attr_writer :strip_namespaces + # Returns the response pattern to apply. + def response_pattern + @response_pattern ||= [] + end + + # Sets the response pattern (an Array of Regexps or Symbols). + attr_writer :response_pattern + # Reset to default configuration. def reset_config! self.log = true @@ -69,6 +77,7 @@ def reset_config! self.raise_errors = true self.soap_version = SOAP::DefaultVersion self.strip_namespaces = true + self.response_pattern = [] end end diff --git a/lib/savon/soap/response.rb b/lib/savon/soap/response.rb index 13e6b936..d72ad5ce 100644 --- a/lib/savon/soap/response.rb +++ b/lib/savon/soap/response.rb @@ -44,8 +44,22 @@ def http_error end # Returns the SOAP response body as a Hash. + def original_hash + @original_hash ||= Savon::SOAP::XML.to_hash to_xml + end + + # Returns the SOAP response body as a Hash and applies + # the Savon.response_pattern if defined. def to_hash - @hash ||= Savon::SOAP::XML.to_hash to_xml + @hash ||= apply_response_pattern original_hash + end + + # Returns the SOAP response Hash as an Array. + def to_array + @array ||= begin + array = to_hash.kind_of?(Array) ? to_hash : [to_hash] + array.compact + end end # Returns the SOAP response XML. @@ -60,6 +74,20 @@ def raise_errors raise http_error if http_error? end + def apply_response_pattern(hash) + return hash if Savon.response_pattern.blank? + + Savon.response_pattern.inject(hash) do |memo, pattern| + key = case pattern + when Regexp then memo.keys.find { |key| key.to_s =~ pattern } + else memo.keys.find { |key| key.to_s == pattern.to_s } + end + + return hash unless key + memo[key] + end + end + end end end diff --git a/spec/savon/savon_spec.rb b/spec/savon/savon_spec.rb index 3ed0f6ae..3585b1ff 100644 --- a/spec/savon/savon_spec.rb +++ b/spec/savon/savon_spec.rb @@ -81,5 +81,18 @@ end end + describe "response_pattern" do + it "should default to an empty Array" do + Savon.response_pattern.should == [] + end + + it "should return the response pattern to apply" do + pattern = [/.+_response/, :return] + Savon.configure { |config| config.response_pattern = pattern } + + Savon.response_pattern.should == pattern + end + end end + end diff --git a/spec/savon/soap/response_spec.rb b/spec/savon/soap/response_spec.rb index 495a03c4..ecca8133 100644 --- a/spec/savon/soap/response_spec.rb +++ b/spec/savon/soap/response_spec.rb @@ -116,13 +116,72 @@ end end - describe "#to_hash" do + describe "#original_hash" do it "should return the SOAP response body as a Hash" do - soap_response.to_hash[:authenticate_response][:return].should == + soap_response.original_hash[:authenticate_response][:return].should == ResponseFixture.authentication(:to_hash) end end + describe "#to_hash" do + let(:response) { soap_response } + + it "should memoize the result" do + response.to_hash.should equal(response.to_hash) + end + + context "without response pattern" do + it "should return the original Hash" do + response.to_hash[:authenticate_response].should be_a(Hash) + end + end + + context "with response pattern" do + it "should apply the response pattern" do + Savon.response_pattern = [/.+_response/, :return] + response.to_hash[:success].should be_true + + Savon.response_pattern = nil # reset to default + end + end + + context "with unmatched response pattern" do + it "should return the original Hash" do + Savon.response_pattern = [:unmatched, :pattern] + response.to_hash.should == response.original_hash + + Savon.response_pattern = nil # reset to default + end + end + end + + describe "#to_array" do + let(:response) { soap_response } + + around do |example| + Savon.response_pattern = [/.+_response/, :return] + example.run + Savon.response_pattern = nil # reset to default + end + + it "should memoize the result" do + response.to_array.should equal(response.to_array) + end + + it "should return an Array for a single response element" do + response.to_array.should be_an(Array) + response.to_array.first[:success].should be_true + end + + it "should return an Array for multiple response element" do + Savon.response_pattern = [/.+_response/, :history, :case] + list_response = soap_response :body => ResponseFixture.list + + list_response.to_array.should be_an(Array) + list_response.to_array.should have(2).items + end + end + describe "#to_xml" do it "should return the raw SOAP response body" do soap_response.to_xml.should == ResponseFixture.authentication