diff --git a/CHANGELOG.md b/CHANGELOG.md index f9ee186..3cef61a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * [#319](https://github.com/codegram/hyperclient/pull/319): Fixed `Resource#to_h` returning `nil` instead of the same result as `#to_hash` - [@dblock](https://github.com/dblock). * [#320](https://github.com/codegram/hyperclient/pull/320): Documented how to handle non-`hal+json` responses via the Faraday response middleware's `content_type` matcher - [@dblock](https://github.com/dblock). * [#321](https://github.com/codegram/hyperclient/pull/321): Added Ruby 4.0 to the CI test matrix - [@dblock](https://github.com/dblock). +* [#322](https://github.com/codegram/hyperclient/pull/322): Fixed `Link` caching a mutating request's (`_post`/`_put`/`_patch`/`_delete`) response as its resource, causing subsequent reads (e.g. `#each`, `method_missing`) to return stale data instead of a fresh `_get` - [@dblock](https://github.com/dblock). * Your contribution here. ### 2.0.0 (2024/02/01) diff --git a/lib/hyperclient/link.rb b/lib/hyperclient/link.rb index 7bb7113..864e29b 100644 --- a/lib/hyperclient/link.rb +++ b/lib/hyperclient/link.rb @@ -190,10 +190,19 @@ def _uri_template end def http_method(method, body = nil) - @resource = begin - response = @entry_point.connection.run_request(method, _url, body, nil) - Resource.new(response.body, @entry_point, response) - end + response = @entry_point.connection.run_request(method, _url, body, nil) + resource = Resource.new(response.body, @entry_point, response) + + # Only cache GET responses. Caching the response of a mutating + # request (POST/PUT/PATCH/DELETE) as `@resource` would make + # subsequent delegated calls (e.g. `#each`, `method_missing`) see + # the stale mutation response instead of fetching a fresh + # resource, requiring users to create a new client between a + # `_post` and a `_get`. See #107. + @resource = resource if method == :get + @delegate = nil + + resource end end end diff --git a/test/hyperclient/link_test.rb b/test/hyperclient/link_test.rb index 9c6e73a..2c166b6 100644 --- a/test/hyperclient/link_test.rb +++ b/test/hyperclient/link_test.rb @@ -151,6 +151,19 @@ module Hyperclient link._resource end + + it 'fetches a fresh resource after a mutating request instead of returning the cached response (#107)' do + link = Link.new('key', { 'href' => '/productions/1' }, entry_point) + + stub_request(entry_point.connection) do |stub| + stub.post('http://api.example.org/productions/1') { [201, {}, { 'status' => 'created' }] } + stub.get('http://api.example.org/productions/1') { [200, {}, { 'status' => 'fetched' }] } + end + + link._post('foo' => 'bar') + + _(link._resource.status).must_equal 'fetched' + end end describe 'get' do