Skip to content

Commit

Permalink
fix #291: change :soap_request to an around hook
Browse files Browse the repository at this point in the history
  • Loading branch information
rubiii committed Jun 8, 2012
1 parent 3a14076 commit 9817cfd
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 14 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## UPCOMING

* Improvement: [#291](https://github.com/rubiii/savon/issues/291) changed the `:soap_request` hook to act
like an around filter. The hook now receives a callback block to execute the SOAP call and can return
the result of the callback to continue the request. It can also not call the callback block and return
some `HTTPI::Response` to mock the SOAP request.

As this change affects `savon_spec`, you need to update `savon_spec` to v1.3.0.

## 0.9.14 (2012-06-07)

* Fix: [#292](https://github.com/rubiii/savon/issues/292) again
Expand Down
34 changes: 25 additions & 9 deletions lib/savon/hooks/group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ module Hooks
class Group

# Accepts an Array of +hooks+ to start with.
def initialize(hooks = nil)
self.hooks = hooks
def initialize(hooks = [])
@hooks = hooks
end

attr_writer :hooks

def hooks
@hooks ||= []
def empty?
hooks.empty?
end

# Adds a new hook.
Expand All @@ -30,9 +28,16 @@ def reject!(*ids)
hooks.reject! { |hook| ids.include? hook.id }
end

# Returns a new group for a given +hook+.
def select(hook)
Group.new hooks.select { |h| h.hook == hook }
# Fire a given +hook+ with any given +args+.
def fire(hook, *args, &callback)
callable = select(hook)

if callable.empty?
callback.call
else
args.unshift(callback) if callback
callable.call(*args)
end
end

# Calls the hooks with the given +args+ and returns the
Expand All @@ -41,6 +46,17 @@ def call(*args)
hooks.inject(nil) { |memo, hook| hook.call(*args) }
end

private

def hooks
@hooks ||= []
end

# Returns a new group for a given +hook+.
def select(hook)
Group.new hooks.select { |h| h.hook == hook }
end

end
end
end
2 changes: 1 addition & 1 deletion lib/savon/soap/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def initialize(config, http, soap)
# Executes the request and returns the response.
def response
@response ||= begin
response = config.hooks.select(:soap_request).call(self) || with_logging { HTTPI.post(http) }
response = config.hooks.fire(:soap_request, self) { with_logging { HTTPI.post(http) } }
SOAP::Response.new(config, response)
end
end
Expand Down
40 changes: 36 additions & 4 deletions spec/savon/soap/request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

describe Savon::SOAP::Request do

let(:soap_request) { Savon::SOAP::Request.new(config, http_request, soap_xml) }
let(:http_request) { HTTPI::Request.new }
let(:soap_request) { Savon::SOAP::Request.new(config, http_request, soap_xml) }
let(:http_request) { HTTPI::Request.new }
let(:http_response) { HTTPI::Response.new 200, {}, Fixture.response(:authentication) }

let(:config) {
config = Savon::Config.default
Expand Down Expand Up @@ -31,7 +32,7 @@ def soap_xml!(endpoint = nil, input = nil, body = nil)

describe ".execute" do
it "executes a SOAP request and returns the response" do
HTTPI.expects(:post).returns(HTTPI::Response.new 200, {}, Fixture.response(:authentication))
HTTPI.expects(:post).returns(http_response)
response = Savon::SOAP::Request.execute config, http_request, soap_xml
response.should be_a(Savon::SOAP::Response)
end
Expand Down Expand Up @@ -72,9 +73,40 @@ def soap_xml!(endpoint = nil, input = nil, body = nil)

describe "#response" do
it "executes an HTTP POST request and returns a Savon::SOAP::Response" do
HTTPI.expects(:post).returns(HTTPI::Response.new 200, {}, Fixture.response(:authentication))
HTTPI.expects(:post).returns(http_response)
soap_request.response.should be_a(Savon::SOAP::Response)
end

context "with a :soap_request hook" do
it "lets you replace the HTTP request and return your own response" do
config.hooks.define(:test, :soap_request) do |_, request|
request.should be_a(Savon::SOAP::Request)
http_response
end

response = soap_request.response
response.http.should equal(http_response)
end

it "works as an around filter for the SOAP request" do
HTTPI.expects(:post).returns(http_response)
state = []

config.hooks.define(:test, :soap_request) do |callback, request|
state << :before
response = callback.call
state << response
state << :after
response
end

response = soap_request.response

state[0].should == :before
state[1].should be_a(HTTPI::Response)
state[2].should == :after
end
end
end

end

0 comments on commit 9817cfd

Please sign in to comment.