hyperclient 1.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +18 -0
  3. data/.github/workflows/coverage.yml +21 -0
  4. data/.github/workflows/danger-comment.yml +11 -0
  5. data/.github/workflows/danger.yml +13 -0
  6. data/.github/workflows/lint.yml +16 -0
  7. data/.github/workflows/test.yml +28 -0
  8. data/.gitignore +1 -0
  9. data/.rubocop.yml +5 -0
  10. data/.rubocop_todo.yml +40 -31
  11. data/AGENTS.md +26 -0
  12. data/CHANGELOG.md +21 -3
  13. data/CONTRIBUTING.md +11 -1
  14. data/Dangerfile +2 -0
  15. data/Gemfile +10 -7
  16. data/README.md +49 -44
  17. data/RELEASING.md +47 -41
  18. data/Rakefile +0 -8
  19. data/examples/oxford/README.md +42 -0
  20. data/examples/oxford/app.rb +48 -0
  21. data/examples/oxford/client.rb +13 -0
  22. data/examples/oxford/places.json +21 -0
  23. data/examples/oxford/server.rb +13 -0
  24. data/features/steps/api_navigation.rb +3 -3
  25. data/features/steps/default_config.rb +2 -2
  26. data/features/support/api.rb +22 -11
  27. data/features/support/env.rb +15 -1
  28. data/hyperclient.gemspec +4 -4
  29. data/lib/hyperclient/entry_point.rb +3 -3
  30. data/lib/hyperclient/link.rb +13 -4
  31. data/lib/hyperclient/resource.rb +13 -3
  32. data/lib/hyperclient/resource_collection.rb +1 -3
  33. data/lib/hyperclient/version.rb +1 -1
  34. data/test/hyperclient/attributes_test.rb +9 -0
  35. data/test/hyperclient/collection_test.rb +22 -0
  36. data/test/hyperclient/curie_test.rb +7 -0
  37. data/test/hyperclient/entry_point_test.rb +35 -13
  38. data/test/hyperclient/link_collection_test.rb +10 -0
  39. data/test/hyperclient/link_test.rb +128 -1
  40. data/test/hyperclient/resource_test.rb +36 -2
  41. data/test/hyperclient_test.rb +6 -5
  42. data/test/oxford_example_test.rb +52 -0
  43. data/test/test_helper.rb +19 -1
  44. metadata +25 -33
  45. data/.travis.yml +0 -24
  46. data/examples/splines_api.rb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f55cb82362d8eca25347e15c91387bbf2957f1f1241af27fccff1086b412d1b
4
- data.tar.gz: f31325a293b0aec888b94910b8c3dc28d2f30a6666fe59063b4112251f46e7c4
3
+ metadata.gz: f6f97641ae8ac6b8ee5e917bb42885454ccfa4dfbe29f91fbe488266c3d8df1b
4
+ data.tar.gz: 1b4da773e4b20cb6e4ba0e4acec481d586b9101d1cbc6010e0072b9366e7e495
5
5
  SHA512:
6
- metadata.gz: e9b17e112614d3c600497c6c7cfd56268195427da789629d006742ff96e70d2b6972ba16fbfa075ab62613eeace923d8fdb4f231b9d86a04f82b75fa5d4a4826
7
- data.tar.gz: 8a8861e266967702c86d5762ec5b786687298c37e797a5c324583c9d3c9d2fe4dc83cf8841c912db3d14a0bf731d1dbee0c1c85b3d43961589c5741b43b3f128
6
+ metadata.gz: 9786c186df822fa748372f4ad8591f949f53ea37625e78946da83e16572bec228e59c0cbfea2bb5f287c6b81f513e2a7b3c46ce98a7c0f8d48dc6ca88d4792ef
7
+ data.tar.gz: 8a525a635faa47057352eb5bfb8cde4d65a3d81fd41e9a2c536bc465170249fa0dc8f84d00f8f7e865bb849a076160ce6ec9dc02ba8ac637c2dbc88a8c399e72
@@ -0,0 +1,18 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ time: "04:00"
8
+ timezone: Europe/Madrid
9
+ open-pull-requests-limit: 10
10
+ ignore:
11
+ - dependency-name: rubocop
12
+ versions:
13
+ - 1.10.0
14
+ - 1.11.0
15
+ - 1.12.0
16
+ - 1.12.1
17
+ - 1.9.0
18
+ - 1.9.1
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: coverage
3
+ on: [push, pull_request]
4
+
5
+ env:
6
+ COVERAGE: 1
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v3
13
+ - uses: ruby/setup-ruby@v1
14
+ with:
15
+ ruby-version: '4.0'
16
+ bundler-cache: true
17
+ - run: |
18
+ bundle exec rake test spinach
19
+ - uses: coverallsapp/github-action@v2
20
+ with:
21
+ github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,11 @@
1
+ name: Danger Comment
2
+
3
+ on:
4
+ workflow_run:
5
+ workflows: [Danger]
6
+ types: [completed]
7
+
8
+ jobs:
9
+ comment:
10
+ uses: numbata/danger-pr-comment/.github/workflows/danger-comment.yml@v0.1.0
11
+ secrets: inherit
@@ -0,0 +1,13 @@
1
+ name: Danger
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, reopened, edited, synchronize]
6
+
7
+ jobs:
8
+ danger:
9
+ uses: numbata/danger-pr-comment/.github/workflows/danger-run.yml@v0.1.0
10
+ secrets: inherit
11
+ with:
12
+ ruby-version: '4.0'
13
+ bundler-cache: true
@@ -0,0 +1,16 @@
1
+ name: lint
2
+ on: [push, pull_request]
3
+ jobs:
4
+ rubocop:
5
+ name: RuboCop
6
+ runs-on: ubuntu-latest
7
+ steps:
8
+ - name: Checkout
9
+ uses: actions/checkout@v3
10
+ - name: Set up Ruby
11
+ uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: '4.0'
14
+ bundler-cache: true
15
+ - run: bundle exec rubocop
16
+
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: test
3
+ on: [push, pull_request]
4
+ jobs:
5
+ test:
6
+ runs-on: ubuntu-latest
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ entry:
11
+ - { ruby: '4.0' }
12
+ - { ruby: '3.4' }
13
+ - { ruby: '3.2', json: '2' }
14
+ - { ruby: '3.2' }
15
+ - { ruby: '2.7', json: '2' }
16
+ - { ruby: 'ruby-head', allowed-failure: true }
17
+ - { ruby: 'jruby-head', allowed-failure: true }
18
+ name: test (Ruby ${{ matrix.entry.ruby }}, JSON ${{ matrix.entry.json || '3' }})
19
+ env:
20
+ JSON_VERSION: ${{ matrix.entry.json || '3' }}
21
+ steps:
22
+ - uses: actions/checkout@v3
23
+ - uses: ruby/setup-ruby@v1
24
+ with:
25
+ ruby-version: ${{ matrix.entry.ruby }}
26
+ bundler-cache: true
27
+ - run: bundle exec rake test spinach
28
+ continue-on-error: ${{ matrix.entry.allowed-failure || false }}
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  *.gem
2
+ .DS_Store
2
3
  *.rbc
3
4
  .bundle
4
5
  .config
data/.rubocop.yml CHANGED
@@ -1,6 +1,11 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
+ plugins:
4
+ - rubocop-rake
5
+ - rubocop-minitest
6
+
3
7
  AllCops:
8
+ NewCops: enable
4
9
  TargetRubyVersion: 2.3
5
10
 
6
11
  Metrics:
data/.rubocop_todo.yml CHANGED
@@ -1,21 +1,55 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2020-12-03 14:08:14 -0500 using RuboCop version 0.81.0.
3
+ # on 2025-09-10 13:55:47 UTC using RuboCop version 1.80.2.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 2
10
- # Cop supports --auto-correct.
11
- # Configuration parameters: AutoCorrect, EnforcedStyle.
9
+ # Offense count: 1
10
+ # Configuration parameters: Severity.
11
+ Gemspec/RequiredRubyVersion:
12
+ Exclude:
13
+ - 'hyperclient.gemspec'
14
+
15
+ # Offense count: 1
16
+ # Configuration parameters: AllowComments, AllowEmptyLambdas.
17
+ Lint/EmptyBlock:
18
+ Exclude:
19
+ - 'test/hyperclient/entry_point_test.rb'
20
+
21
+ # Offense count: 4
22
+ # Configuration parameters: AllowedParentClasses.
23
+ Lint/MissingSuper:
24
+ Exclude:
25
+ - 'lib/hyperclient/attributes.rb'
26
+ - 'lib/hyperclient/entry_point.rb'
27
+ - 'lib/hyperclient/link_collection.rb'
28
+ - 'lib/hyperclient/resource_collection.rb'
29
+
30
+ # Offense count: 1
31
+ # This cop supports unsafe autocorrection (--autocorrect-all).
32
+ # Configuration parameters: AllowedMethods, InferNonNilReceiver, AdditionalNilMethods.
33
+ # AllowedMethods: instance_of?, kind_of?, is_a?, eql?, respond_to?, equal?
34
+ # AdditionalNilMethods: present?, blank?, try, try!
35
+ Lint/RedundantSafeNavigation:
36
+ Exclude:
37
+ - 'lib/hyperclient/link.rb'
38
+
39
+ # Offense count: 3
40
+ # This cop supports unsafe autocorrection (--autocorrect-all).
41
+ # Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules.
12
42
  # SupportedStyles: nested, compact
43
+ # SupportedStylesForClasses: ~, nested, compact
44
+ # SupportedStylesForModules: ~, nested, compact
13
45
  Style/ClassAndModuleChildren:
14
46
  Exclude:
15
47
  - 'features/steps/api_navigation.rb'
16
48
  - 'features/steps/default_config.rb'
49
+ - 'features/support/env.rb'
17
50
 
18
- # Offense count: 4
51
+ # Offense count: 5
52
+ # Configuration parameters: AllowedConstants.
19
53
  Style/Documentation:
20
54
  Exclude:
21
55
  - 'spec/**/*'
@@ -23,30 +57,5 @@ Style/Documentation:
23
57
  - 'features/steps/api_navigation.rb'
24
58
  - 'features/steps/default_config.rb'
25
59
  - 'features/support/api.rb'
60
+ - 'features/support/env.rb'
26
61
  - 'features/support/fixtures.rb'
27
-
28
- # Offense count: 2
29
- Style/DoubleNegation:
30
- Exclude:
31
- - 'lib/hyperclient/curie.rb'
32
- - 'lib/hyperclient/link.rb'
33
-
34
- # Offense count: 3
35
- # Cop supports --auto-correct.
36
- Style/IfUnlessModifier:
37
- Exclude:
38
- - 'lib/hyperclient/link_collection.rb'
39
- - 'lib/hyperclient/resource.rb'
40
- - 'lib/hyperclient/resource_collection.rb'
41
-
42
- # Offense count: 1
43
- Style/MethodMissingSuper:
44
- Exclude:
45
- - 'lib/hyperclient/collection.rb'
46
-
47
- # Offense count: 101
48
- # Cop supports --auto-correct.
49
- # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
50
- # URISchemes: http, https
51
- Layout/LineLength:
52
- Max: 147
data/AGENTS.md ADDED
@@ -0,0 +1,26 @@
1
+ # Agent Guide
2
+
3
+ Hyperclient is a Ruby client for JSON HAL APIs, built on Faraday 2 and `faraday_hal_middleware`.
4
+
5
+ ## Layout
6
+
7
+ - `lib/hyperclient.rb`: client entry point and configuration.
8
+ - `lib/hyperclient/`: resources, links, collections, attributes, and CURIEs.
9
+ - `test/`: Minitest tests and fixtures.
10
+ - `features/`: Spinach acceptance tests and supporting code.
11
+ - `examples/`: runnable usage examples.
12
+
13
+ ## Commands
14
+
15
+ ```sh
16
+ bundle install
17
+ bundle exec rake # Minitest, Spinach, and RuboCop
18
+ bundle exec rake test # Minitest only
19
+ bundle exec rake spinach # Acceptance tests only
20
+ bundle exec rake rubocop # Lint
21
+ bundle exec ruby -Itest test/hyperclient_test.rb
22
+ ```
23
+
24
+ ## Changes
25
+
26
+ Follow existing Ruby conventions and preserve Ruby 2.7 compatibility. Add regression tests for behavior changes; use existing HTTP stubs rather than depending on external services. Update the README for public API changes and the changelog with the pull request number. See `CONTRIBUTING.md` for the full contribution workflow and `.github/workflows/` for the CI matrix.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  ## Changelog
2
2
 
3
+ ### 2.1.0 (2026/10/14)
4
+
5
+ * [#328](https://github.com/codegram/hyperclient/pull/328): Replaced the retired Splines demo with a local read-only Oxford HAL example using archived place facts - [@dblock](https://github.com/dblock).
6
+ * [#298](https://github.com/codegram/hyperclient/pull/300): Upgraded RuboCop to 1.80.2 - [@dblock](https://github.com/dblock).
7
+ * [#298](https://github.com/codegram/hyperclient/pull/298): Upgraded RuboCop to 1.63.5 - [@dblock](https://github.com/dblock).
8
+ * [#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).
9
+ * [#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).
10
+ * [#321](https://github.com/codegram/hyperclient/pull/321): Added Ruby 4.0 to the CI test matrix - [@dblock](https://github.com/dblock).
11
+ * [#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).
12
+ * [#325](https://github.com/codegram/hyperclient/pull/325): Added JSON 2.x/3.x to the CI matrix and JSON response parsing regression tests, retaining Ruby 2.7 coverage with JSON 2.x; upgraded RuboCop to 1.91.0 to allow JSON 3.x - [@dblock](https://github.com/dblock).
13
+ ### 2.0.0 (2024/02/01)
14
+
15
+ * [#268](https://github.com/codegram/hyperclient/pull/268): Replace Travis-CI with GHA - [@dblock](https://github.com/dblock).
16
+ * [#269](https://github.com/codegram/hyperclient/pull/269): Re-add code coverage - [@dblock](https://github.com/dblock).
17
+ * [#270](https://github.com/codegram/hyperclient/pull/270): Upgrade RuboCop to 1.45 - [@dblock](https://github.com/dblock).
18
+ * [#271](https://github.com/codegram/hyperclient/pull/271): Test against Ruby 3.2 - [@dblock](https://github.com/dblock).
19
+ * [#285](https://github.com/codegram/hyperclient/pull/285): Support Faraday 2.x - [@dblock](https://github.com/dblock).
20
+
3
21
  ### 1.0.1 (2021/01/02)
4
22
 
5
23
  * [#193](https://github.com/codegram/hyperclient/pull/193): Auto-paginate collections - [@dblock](https://github.com/dblock).
@@ -31,14 +49,14 @@
31
49
  ### 0.9.0 (2018/01/10)
32
50
 
33
51
  * [#133](https://github.com/codegram/hyperclient/pull/133): Removed futuroscope - [@dblock](https://github.com/dblock).
34
- * [#131](https://github.com/codegram/hyperclient/pull/131): Upgrade to Rubocop 0.50.0, fix Bundler's insecure git source warning - [@nebolsin](https://github.com/nebolsin).
52
+ * [#131](https://github.com/codegram/hyperclient/pull/131): Upgrade to RuboCop 0.50.0, fix Bundler's insecure git source warning - [@nebolsin](https://github.com/nebolsin).
35
53
  * [#132](https://github.com/codegram/hyperclient/pull/132): Swapped yard dependency for danger-toc - [@dblock](https://github.com/dblock).
36
54
 
37
55
  ### 0.8.6 (2017/08/27)
38
56
 
39
57
  * [#122](https://github.com/codegram/hyperclient/pull/122): Improve error message when server returns invalid data - [@ivoanjo](https://github.com/ivoanjo).
40
58
  * [#125](https://github.com/codegram/hyperclient/pull/125): Add table of contents to readme and add note asking users to add their projects to the wiki - [@ivoanjo](https://github.com/ivoanjo).
41
- * [#127](https://github.com/codegram/hyperclient/pull/127): Minor fixes: Fix warnings, and pry-byebug to dev Gemfile and tweak rubocop execution - [@ivoanjo](https://github.com/ivoanjo).
59
+ * [#127](https://github.com/codegram/hyperclient/pull/127): Minor fixes: Fix warnings, and pry-byebug to dev Gemfile and tweak RuboCop execution - [@ivoanjo](https://github.com/ivoanjo).
42
60
  * [#128](https://github.com/codegram/hyperclient/pull/128): Fix link delegation returning nil for field with value false - [@ivoanjo](https://github.com/ivoanjo).
43
61
 
44
62
  ### 0.8.5 (2017/07/05)
@@ -99,7 +117,7 @@
99
117
  * [#64](https://github.com/codegram/hyperclient/issues/64): Added support for curies - [@dblock](https://github.com/dblock).
100
118
  * [#58](https://github.com/codegram/hyperclient/issues/58): Automatically follow redirects - [@dblock](https://github.com/dblock).
101
119
  * [#63](https://github.com/codegram/hyperclient/pull/63): You can omit the navigational elements, `api.links.products` is now equivalent to `api.products` - [@dblock](https://github.com/dblock).
102
- * [#61](https://github.com/codegram/hyperclient/pull/61): Implemented Rubocop, Ruby-style linter - [@dblock](https://github.com/dblock).
120
+ * [#61](https://github.com/codegram/hyperclient/pull/61): Implemented RuboCop, Ruby-style linter - [@dblock](https://github.com/dblock).
103
121
 
104
122
  ### 0.4.0 (2014/05/05)
105
123
 
data/CONTRIBUTING.md CHANGED
@@ -32,6 +32,16 @@ bundle install
32
32
  bundle exec rake
33
33
  ```
34
34
 
35
+ CI runs the test suites with JSON 2.x on Ruby 2.7, both JSON 2.x and 3.x on Ruby 3.2, and JSON 3.x on Ruby 3.4, Ruby 4.0, and the head builds.
36
+ To select a JSON major version locally, resolve the bundle and run the tests with the same `JSON_VERSION`:
37
+
38
+ ```
39
+ JSON_VERSION=2 bundle update json
40
+ JSON_VERSION=2 bundle exec rake test spinach
41
+ JSON_VERSION=3 bundle update json
42
+ JSON_VERSION=3 bundle exec rake test spinach
43
+ ```
44
+
35
45
  #### Write Tests
36
46
 
37
47
  Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build. Add to [test/hyperclient](test/hyperclient).
@@ -106,7 +116,7 @@ git push origin my-feature-branch -f
106
116
 
107
117
  #### Check on Your Pull Request
108
118
 
109
- Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above.
119
+ Go back to your pull request after a few minutes and see whether it passed muster with CI. Everything should look green, otherwise fix issues and amend your commit as described above.
110
120
 
111
121
  #### Be Patient
112
122
 
data/Dangerfile CHANGED
@@ -1,2 +1,4 @@
1
+ danger.import_dangerfile(gem: 'danger-pr-comment')
2
+
1
3
  changelog.check!
2
4
  toc.check!
data/Gemfile CHANGED
@@ -1,12 +1,9 @@
1
- # NOTE: this is temporary until Bundler 2.0 changes how github: references work.
2
- git_source(:github) { |repo| "https://github.com/#{repo['/'] ? repo : "#{repo}/#{repo}"}.git" }
3
-
4
1
  source 'https://rubygems.org'
5
2
 
6
- gem 'faraday', ENV['FARADAY_VERSION'] if ENV.key?('FARADAY_VERSION')
7
-
8
3
  gemspec
9
4
 
5
+ gem 'json', "~> #{ENV['JSON_VERSION']}.0" if ENV['JSON_VERSION']
6
+
10
7
  group :development do
11
8
  gem 'growl'
12
9
  gem 'guard'
@@ -18,12 +15,18 @@ end
18
15
 
19
16
  group :development, :test do
20
17
  gem 'rake'
21
- gem 'rubocop', '0.81.0', require: false
18
+ gem 'rubocop', '~> 1.92.0', require: false
19
+ gem 'rubocop-minitest', require: false
20
+ gem 'rubocop-rake', require: false
22
21
  gem 'simplecov', require: false
22
+ gem 'simplecov-lcov', require: false
23
+ gem 'webrick', '~> 1.8'
23
24
  end
24
25
 
25
26
  group :test do
26
- gem 'danger-changelog', '~> 0.6.0'
27
+ gem 'danger', '~> 9.5'
28
+ gem 'danger-changelog', '~> 0.8.0'
29
+ gem 'danger-pr-comment', '~> 0.1.0'
27
30
  gem 'danger-toc', '~> 0.2.0'
28
31
  gem 'minitest'
29
32
  gem 'mocha'
data/README.md CHANGED
@@ -1,9 +1,8 @@
1
1
  # Hyperclient
2
2
 
3
3
  [![Gem Version](http://img.shields.io/gem/v/hyperclient.svg)](http://badge.fury.io/rb/hyperclient)
4
- [![Build Status](http://img.shields.io/travis/codegram/hyperclient.svg)](https://travis-ci.org/codegram/hyperclient)
5
- [![Code Climate](https://codeclimate.com/github/codegram/hyperclient.svg)](https://codeclimate.com/github/codegram/hyperclient)
6
- [![Coverage Status](https://img.shields.io/coveralls/codegram/hyperclient.svg)](https://coveralls.io/r/codegram/hyperclient?branch=master)
4
+ [![Build Status](https://github.com/codegram/hyperclient/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/codegram/hyperclient/actions/workflows/test.yml)
5
+ [![Coverage Status](https://coveralls.io/repos/github/codegram/hyperclient/badge.svg?branch=master)](https://coveralls.io/github/codegram/hyperclient?branch=master)
7
6
 
8
7
  Hyperclient is a Hypermedia API client written in Ruby. It fully supports [JSON HAL](http://stateless.co/hal_specification.html).
9
8
 
@@ -25,7 +24,9 @@ Hyperclient is a Hypermedia API client written in Ruby. It fully supports [JSON
25
24
 
26
25
  # Usage
27
26
 
28
- The examples in this README use the [Splines Demo API](https://github.com/ruby-grape/grape-with-roar) running [here](https://grape-with-roar.herokuapp.com/api). If you're upgrading from a previous version, please make sure to read [UPGRADING](UPGRADING.md).
27
+ The examples in this README use the [local Oxford HAL demo](examples/oxford/README.md), based on historical Oxford place facts. Start it with `bundle exec ruby examples/oxford/server.rb`, then run `bundle exec ruby -Ilib examples/oxford/client.rb` in another terminal. No external service is needed. Use version 1.x with Faraday 1.x, and version 2.x with Faraday 2.x. If you're upgrading from a previous version, please make sure to read [UPGRADING](UPGRADING.md).
28
+
29
+ Hyperclient is tested with JSON 2.x on Ruby 2.7, both JSON 2.x and 3.x on Ruby 3.2, and JSON 3.x on newer Rubies. JSON 3.x requires a Faraday release with keyword parser options support (2.14.4+).
29
30
 
30
31
  ## API Client
31
32
 
@@ -34,13 +35,13 @@ Create an API client.
34
35
  ```ruby
35
36
  require 'hyperclient'
36
37
 
37
- api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api')
38
+ api = Hyperclient.new('http://127.0.0.1:9292/')
38
39
  ```
39
40
 
40
41
  By default, Hyperclient adds `application/hal+json` as `Content-Type` and `Accept` headers. It will also send requests as JSON and parse JSON responses. Specify additional headers or authentication if necessary.
41
42
 
42
43
  ```ruby
43
- api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
44
+ api = Hyperclient.new('http://127.0.0.1:9292/') do |client|
44
45
  client.headers['Access-Token'] = 'token'
45
46
  end
46
47
  ```
@@ -48,9 +49,9 @@ end
48
49
  Hyperclient constructs a connection using typical [Faraday](http://github.com/lostisland/faraday) middleware for handling JSON requests and responses. You can specify additional Faraday middleware if necessary.
49
50
 
50
51
  ```ruby
51
- api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
52
+ api = Hyperclient.new('http://127.0.0.1:9292/') do |client|
52
53
  client.connection do |conn|
53
- conn.use Faraday::Request::OAuth
54
+ conn.use Faraday::Request::Instrumentation
54
55
  end
55
56
  end
56
57
  ```
@@ -58,9 +59,9 @@ end
58
59
  You can pass options to the Faraday connection block in the `connection` block:
59
60
 
60
61
  ```ruby
61
- api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
62
+ api = Hyperclient.new('http://127.0.0.1:9292/') do |client|
62
63
  client.connection(ssl: { verify: false }) do |conn|
63
- conn.use Faraday::Request::OAuth
64
+ conn.use Faraday::Request::Instrumentation
64
65
  end
65
66
  end
66
67
  ```
@@ -68,7 +69,7 @@ end
68
69
  Or when using the default connection configuration you can use `faraday_options`:
69
70
 
70
71
  ```ruby
71
- api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
72
+ api = Hyperclient.new('http://127.0.0.1:9292/') do |client|
72
73
  client.faraday_options = { ssl: { verify: false } }
73
74
  end
74
75
  ```
@@ -76,7 +77,7 @@ end
76
77
  You can build a new Faraday connection block without inheriting default middleware by specifying `default: false` in the `connection` block.
77
78
 
78
79
  ```ruby
79
- api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
80
+ api = Hyperclient.new('http://127.0.0.1:9292/') do |client|
80
81
  client.connection(default: false) do |conn|
81
82
  conn.request :json
82
83
  conn.response :json, content_type: /\bjson$/
@@ -85,12 +86,14 @@ api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
85
86
  end
86
87
  ```
87
88
 
89
+ By default, Hyperclient requires responses to have a `Content-Type` of `application/hal+json`, and raises `Hyperclient::InvalidRepresentationError` otherwise. If your API sometimes returns responses that aren't `hal+json` (e.g. an empty body with a `201 Created`, or a plain `application/json` response), broaden the response middleware's `content_type` matcher as shown above (`content_type: /\bjson$/`) instead of the default, which only matches `hal+json`.
90
+
88
91
  You can modify headers or specify authentication after a connection has been created. Hyperclient supports Basic, Token or [Digest auth](https://github.com/bhaberer/faraday-digestauth) as well as many other Faraday extensions.
89
92
 
90
93
  ```ruby
91
94
  require 'faraday/digestauth'
92
95
 
93
- api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
96
+ api = Hyperclient.new('http://127.0.0.1:9292/') do |client|
94
97
  client.connection(default: false) do |conn|
95
98
  conn.request :digest, 'username', 'password'
96
99
  conn.request :json
@@ -103,7 +106,7 @@ end
103
106
  You can access the Faraday connection directly after it has been created and add middleware to it. As an example, you could use the [faraday-http-cache-middleware](https://github.com/plataformatec/faraday-http-cache).
104
107
 
105
108
  ```ruby
106
- api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api')
109
+ api = Hyperclient.new('http://127.0.0.1:9292/')
107
110
  api.connection.use :http_cache
108
111
  ```
109
112
 
@@ -112,48 +115,54 @@ api.connection.use :http_cache
112
115
  Hyperclient will fetch and discover the resources from your API and automatically paginate when possible.
113
116
 
114
117
  ```ruby
115
- api.splines.each do |spline|
116
- puts "A spline with ID #{spline.uuid}."
118
+ api.places.each do |place|
119
+ puts "#{place.name} has ID #{place.id}."
117
120
  end
118
121
  ```
119
122
 
120
123
  Other methods, including `[]` and `fetch` are also available
121
124
 
122
125
  ```ruby
123
- api.splines.each do |spline|
124
- puts "A spline with ID #{spline[:uuid]}."
125
- puts "Maybe with reticulated: #{spline.fetch(:reticulated, '-- no reticulated')}"
126
+ api.places.each do |place|
127
+ puts "A place with ID #{place[:id]}."
128
+ puts "Address: #{place.fetch(:address, '-- no address')}"
126
129
  end
127
130
  ```
128
131
 
129
132
  ## Links and Embedded Resources
130
133
 
131
- The splines example above followed a link called "splines". While you can, you do not need to specify the HAL navigational structure, including links or embedded resources. Hyperclient will resolve these for you. If you prefer, you can explicitly navigate the link structure via `_links`. In the following example the "splines" link leads to a collection of embedded splines. Invoking `api.splines` is equivalent to `api._links.splines._embedded.splines`.
134
+ The example above follows the `places` link to a collection of embedded places. Hyperclient resolves links and embedded resources automatically. You can also navigate explicitly:
132
135
 
133
136
  ```ruby
134
- api._links.splines
137
+ api._links.places._embedded.places.each do |place|
138
+ puts place.name
139
+ end
140
+
141
+ place = api.place(id: 'oxpoints:23232339')
142
+ puts place.primary_place.name # follows a relative link to Balliol College
143
+ puts place._embedded.files.first.url # reads embedded metadata, without fetching the image
135
144
  ```
136
145
 
137
146
  ## Templated Links
138
147
 
139
- Templated links require variables to be expanded. For example, the demo API has a link called "spline" that requires a spline "uuid".
148
+ Templated links require variables to be expanded. The local demo adds a `place` link that accepts an Oxford place ID.
140
149
 
141
150
  ```ruby
142
- spline = api.spline(uuid: 'uuid')
143
- puts "Spline #{spline.uuid} is #{spline.reticulated ? 'reticulated' : 'not reticulated'}."
151
+ place = api.place(id: 'oxpoints:23232339')
152
+ puts place.name # => Balliol College
144
153
  ```
145
154
 
146
- Invoking `api.spline(uuid: 'uuid').reticulated` is equivalent to `api._links.spline._expand(uuid: 'uuid')._resource._attributes.reticulated`.
155
+ Invoking `api.place(id: 'oxpoints:23232339').name` is equivalent to `api._links.place._expand(id: 'oxpoints:23232339')._resource._attributes.name`.
147
156
 
148
157
  The client is responsible for supplying all the necessary parameters. Templated links don't do any strict parameter name checking and don't support required vs. optional parameters. Parameters not declared by the API will be dropped and will not have any effect when passed to `_expand`.
149
158
 
150
159
  ## Curies
151
160
 
152
- Curies are a suggested means by which to link documentation of a given resource. For example, the demo API contains very long links to images that use an "images" curie.
161
+ Curies provide compact names for relation documentation. The local demo adds an `oxford` CURIE and an `oxford:places` relation.
153
162
 
154
163
  ```ruby
155
- puts spline['image:thumbnail'] # => https://grape-with-roar.herokuapp.com/api/splines/uuid/images/thumbnail.jpg
156
- puts spline.links._curies['image'].expand('thumbnail') # => /docs/images/thumbnail
164
+ puts api._links['oxford:places']._embedded.places.first.name # => Balliol College
165
+ puts api._links._curies['oxford'].expand('places') # => /docs/places
157
166
  ```
158
167
 
159
168
  ## Attributes
@@ -161,10 +170,10 @@ puts spline.links._curies['image'].expand('thumbnail') # => /docs/images/thumbna
161
170
  Resource attributes can also be accessed as a hash.
162
171
 
163
172
  ```ruby
164
- puts spline.to_h # => {"uuid" => "uuid", "reticulated" => true}
173
+ puts place.to_h['name'] # => Balliol College
165
174
  ```
166
175
 
167
- The above is equivalent to `spline._attributes.to_h`.
176
+ `place.to_h` is equivalent to `place._attributes.to_h`.
168
177
 
169
178
  ## HTTP
170
179
 
@@ -180,31 +189,27 @@ api._response.body
180
189
  Other methods, including `_head` or `_options` are also available.
181
190
 
182
191
  ```ruby
183
- spline = api.spline(uuid: 'uuid')
184
- spline._head
185
- spline._options
192
+ place = api.place(id: 'oxpoints:23232339')
193
+ place._head
186
194
  ```
187
195
 
188
- Invoke `_post` to create resources.
196
+ The Oxford demo is read-only and rejects writes with HTTP 405. On a writable API, invoke `_post` to create resources:
189
197
 
190
198
  ```ruby
191
- splines = api.splines
192
- splines._post(uuid: 'new uuid', reticulated: false)
199
+ api.places._post(name: 'New place')
193
200
  ```
194
201
 
195
202
  Invoke `_put` or `_patch` to update resources.
196
203
 
197
204
  ```ruby
198
- spline = api.spline(uuid: 'uuid')
199
- spline._put(reticulated: true)
200
- spline._patch(reticulated: true)
205
+ place._put(name: 'Updated place')
206
+ place._patch(name: 'Updated place')
201
207
  ```
202
208
 
203
209
  Invoke `_delete` to destroy a resource.
204
210
 
205
211
  ```
206
- spline = api.spline(uuid: 'uuid')
207
- spline._delete
212
+ place._delete
208
213
  ```
209
214
 
210
215
  HTTP methods always return a new instance of Resource.
@@ -230,13 +235,13 @@ describe Acme::Api do
230
235
  end
231
236
  end
232
237
 
233
- it 'splines returns 3 splines by default' do
234
- expect(client.splines.count).to eq 3
238
+ it 'returns a place' do
239
+ expect(client.places.first.name).to eq 'Balliol College'
235
240
  end
236
241
  end
237
242
  ```
238
243
 
239
- For a complete example refer to [this Splines Demo API test](https://github.com/ruby-grape/grape-with-roar/blob/master/spec/api/splines_endpoint_with_hyperclient_spec.rb).
244
+ For a complete offline example, see the [Oxford demo smoke test](test/oxford_example_test.rb).
240
245
 
241
246
  # Reference
242
247