hyperclient 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +2 -0
  4. data/.rubocop_todo.yml +55 -0
  5. data/.travis.yml +2 -0
  6. data/CHANGELOG.md +33 -10
  7. data/CONTRIBUTING.md +117 -0
  8. data/Gemfile +2 -1
  9. data/Guardfile +6 -6
  10. data/LICENSE +2 -2
  11. data/README.md +138 -0
  12. data/Rakefile +5 -3
  13. data/UPGRADING.md +37 -0
  14. data/examples/splines_api.rb +22 -0
  15. data/features/steps/api_navigation.rb +8 -8
  16. data/features/steps/default_config.rb +6 -6
  17. data/features/support/api.rb +4 -4
  18. data/features/support/fixtures.rb +1 -1
  19. data/hyperclient.gemspec +9 -8
  20. data/lib/faraday/connection.rb +2 -2
  21. data/lib/hyperclient.rb +1 -1
  22. data/lib/hyperclient/attributes.rb +1 -1
  23. data/lib/hyperclient/collection.rb +3 -3
  24. data/lib/hyperclient/curie.rb +49 -0
  25. data/lib/hyperclient/entry_point.rb +6 -4
  26. data/lib/hyperclient/link.rb +70 -58
  27. data/lib/hyperclient/link_collection.rb +36 -11
  28. data/lib/hyperclient/resource.rb +49 -18
  29. data/lib/hyperclient/resource_collection.rb +2 -1
  30. data/lib/hyperclient/version.rb +1 -1
  31. data/test/fixtures/element.json +12 -1
  32. data/test/hyperclient/attributes_test.rb +2 -2
  33. data/test/hyperclient/collection_test.rb +6 -7
  34. data/test/hyperclient/curie_test.rb +34 -0
  35. data/test/hyperclient/entry_point_test.rb +3 -2
  36. data/test/hyperclient/link_collection_test.rb +26 -5
  37. data/test/hyperclient/link_test.rb +111 -86
  38. data/test/hyperclient/resource_collection_test.rb +2 -2
  39. data/test/hyperclient/resource_test.rb +67 -30
  40. data/test/test_helper.rb +2 -2
  41. metadata +54 -39
  42. data/Gemfile.lock +0 -112
  43. data/MIT-LICENSE +0 -20
  44. data/Readme.md +0 -180
  45. data/examples/cyberscore.rb +0 -76
  46. data/examples/hal_shop.rb +0 -53
  47. data/lib/faraday/request/digest_authentication.rb +0 -85
  48. data/test/faraday/digest_authentication_test.rb +0 -41
data/Gemfile.lock DELETED
@@ -1,112 +0,0 @@
1
- GIT
2
- remote: git://github.com/rubyworks/yard-tomdoc
3
- revision: e4b09dcd574718bda91d0f956b4dd83246bda273
4
- specs:
5
- yard-tomdoc (0.7.1)
6
- tomparse (>= 0.4.0)
7
- yard
8
-
9
- PATH
10
- remote: .
11
- specs:
12
- hyperclient (0.4.0)
13
- faraday (~> 0.8)
14
- faraday_middleware (~> 0.9)
15
- futuroscope (>= 0.0.10)
16
- net-http-digest_auth (~> 1.2)
17
- uri_template (~> 0.5)
18
-
19
- GEM
20
- remote: https://rubygems.org/
21
- specs:
22
- addressable (2.3.4)
23
- ansi (1.4.3)
24
- coderay (1.0.9)
25
- colorize (0.5.8)
26
- crack (0.3.2)
27
- faraday (0.8.9)
28
- multipart-post (~> 1.2.0)
29
- faraday_middleware (0.9.0)
30
- faraday (>= 0.7.4, < 0.9)
31
- ffi (1.8.1)
32
- formatador (0.2.4)
33
- futuroscope (0.1.6)
34
- gherkin-ruby (0.3.0)
35
- growl (1.0.3)
36
- guard (1.8.0)
37
- formatador (>= 0.2.4)
38
- listen (>= 1.0.0)
39
- lumberjack (>= 1.0.2)
40
- pry (>= 0.9.10)
41
- thor (>= 0.14.6)
42
- guard-minitest (0.5.0)
43
- guard (>= 0.4)
44
- guard-spinach (0.0.2)
45
- guard (>= 1.1)
46
- spinach
47
- listen (1.0.3)
48
- rb-fsevent (>= 0.9.3)
49
- rb-inotify (>= 0.9)
50
- rb-kqueue (>= 0.2)
51
- lumberjack (1.0.3)
52
- metaclass (0.0.1)
53
- method_source (0.8.1)
54
- minitest (3.4.0)
55
- mocha (0.13.3)
56
- metaclass (~> 0.0.1)
57
- multi_json (1.7.2)
58
- multipart-post (1.2.0)
59
- net-http-digest_auth (1.4)
60
- pry (0.9.12.1)
61
- coderay (~> 1.0.5)
62
- method_source (~> 0.8)
63
- slop (~> 3.4)
64
- rack (1.5.2)
65
- rack-test (0.6.2)
66
- rack (>= 1.0)
67
- rake (10.0.4)
68
- rb-fsevent (0.9.3)
69
- rb-inotify (0.9.0)
70
- ffi (>= 0.5.0)
71
- rb-kqueue (0.2.0)
72
- ffi (>= 0.5.0)
73
- redcarpet (2.2.2)
74
- simplecov (0.7.1)
75
- multi_json (~> 1.0)
76
- simplecov-html (~> 0.7.1)
77
- simplecov-html (0.7.1)
78
- slop (3.4.4)
79
- spinach (0.8.2)
80
- colorize (= 0.5.8)
81
- gherkin-ruby (~> 0.3.0)
82
- thor (0.18.1)
83
- tomparse (0.4.2)
84
- turn (0.9.6)
85
- ansi
86
- uri_template (0.7.0)
87
- webmock (1.11.0)
88
- addressable (>= 2.2.7)
89
- crack (>= 0.3.2)
90
- yard (0.8.6.1)
91
-
92
- PLATFORMS
93
- ruby
94
-
95
- DEPENDENCIES
96
- growl
97
- guard
98
- guard-minitest
99
- guard-spinach
100
- hyperclient!
101
- minitest (~> 3.4.0)
102
- mocha (~> 0.13)
103
- pry
104
- rack-test (~> 0.6)
105
- rake
106
- redcarpet
107
- simplecov
108
- spinach
109
- turn (~> 0.9)
110
- webmock (~> 1.8)
111
- yard (~> 0.8)
112
- yard-tomdoc!
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright 2012 Codegram Technologies
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Readme.md DELETED
@@ -1,180 +0,0 @@
1
- # Hyperclient
2
- [![Build Status](https://secure.travis-ci.org/codegram/hyperclient.png)](http://travis-ci.org/codegram/hyperclient)
3
- [![Dependency Status](https://gemnasium.com/codegram/hyperclient.png)](http://gemnasium.com/codegram/hyperclient)
4
- [![Code Climate](https://codeclimate.com/github/codegram/hyperclient.png)](https://codeclimate.com/github/codegram/hyperclient)
5
-
6
- Hyperclient is a Ruby Hypermedia API client written in Ruby.
7
-
8
- ## Documentation
9
-
10
- [Hyperclient API documentation on rdoc.info][rdoc]
11
-
12
- ## Usage
13
-
14
- Example API client:
15
-
16
- ```ruby
17
- api = Hyperclient.new('http://myapp.com/api').tap do |api|
18
- api.digest_auth('user', 'password')
19
- api.headers.merge({'accept-encoding' => 'deflate, gzip'})
20
- end
21
- ```
22
-
23
- By default, Hyperclient adds `application/json` as `Content-Type` and `Accept`
24
- headers. It will also sent requests as JSON and parse JSON responses.
25
-
26
- [More examples][examples]
27
-
28
- ## HAL
29
-
30
- Hyperclient only works with JSON HAL friendly APIs. [Learn about JSON HAL][hal].
31
-
32
- ## Resources
33
-
34
- Hyperclient will try to fetch and discover the resources from your API.
35
-
36
- ### Links
37
-
38
- Accessing the links for a given resource is quite straightforward:
39
-
40
- ```ruby
41
- api.links.posts_categories
42
- # => #<Resource ...>
43
- ```
44
-
45
- You can also iterate between all the links:
46
-
47
- ```ruby
48
- api.links.each do |name, link|
49
- puts name, link.url
50
- end
51
- ```
52
-
53
- Actually, you can call any [Enumerable][enumerable] method :D
54
-
55
- If a Resource doesn't have friendly name you can always access it as a Hash:
56
-
57
- ```ruby
58
- api.links['http://myapi.org/rels/post_categories']
59
- ```
60
-
61
- ### Embedded resources
62
-
63
- Accessing embedded resources is similar to accessing links:
64
-
65
- ```ruby
66
- api.embedded.posts
67
- ```
68
-
69
- And you can also iterate between them:
70
-
71
- ```ruby
72
- api.embedded.each do |name, resource|
73
- puts name, resource.attributes
74
- end
75
- ```
76
-
77
- You can even chain different calls (this also applies for links):
78
-
79
- ```ruby
80
- api.embedded.posts.first.links.author
81
- ```
82
-
83
- ### Attributes
84
-
85
- Not only you might have links and embedded resources in a Resource, but also
86
- its attributes:
87
-
88
- ```ruby
89
- api.embedded.posts.first.attributes
90
- # => {title: 'Linting the hell out of your Ruby classes with Pelusa',
91
- teaser: 'Gain new insights about your code thanks to static analysis',
92
- body: '...' }
93
- ```
94
-
95
- You can access the attribute values via attribute methods, or as a hash:
96
-
97
- ```ruby
98
- api.embedded.posts.first.attributes.title
99
- # => 'Linting the hell out of your Ruby classes with Pelusa'
100
-
101
- api.embedded.posts.first.attributes['title']
102
- # => 'Linting the hell out of your Ruby classes with Pelusa'
103
-
104
- api.embedded.posts.first.attributes.fetch('title')
105
- # => 'Linting the hell out of your Ruby classes with Pelusa'
106
- ```
107
-
108
- ### HTTP
109
-
110
- OK, navigating an API is really cool, but you may want to actually do something
111
- with it, right?
112
-
113
- Hyperclient uses [Faraday][faraday] under the hood to perform HTTP calls. You can
114
- call any valid HTTP method on any Resource:
115
-
116
- ```ruby
117
- post = api.embedded.posts.first
118
- post.get
119
- post.head
120
- post.put({title: 'New title'})
121
- post.patch({title: 'New title'})
122
- post.delete
123
- post.options
124
-
125
- posts = api.links.posts
126
- posts.post({title: "I'm a blogger!", body: 'Wohoo!!'})
127
- ```
128
-
129
- If you have a templated link you can expand it like so:
130
-
131
- ```ruby
132
- api.links.post.expand(:id => 3).first
133
- # => #<Resource ...>
134
- ```
135
-
136
- You can access the Faraday connection (to add middlewares or do whatever
137
- you want) by calling `connection` on the entry point. As an example, you could use the [faraday-http-cache-middleware](https://github.com/plataformatec/faraday-http-cache)
138
- :
139
-
140
- ```ruby
141
- api.connection.use :http_cache
142
- ```
143
-
144
- ## Other
145
-
146
- There's also a PHP library named [HyperClient](https://github.com/FoxyCart/HyperClient), if that's what you were looking for :)
147
-
148
- ## TODO
149
-
150
- * Resource permissions: Using the `Allow` header Hyperclient should be able to
151
- restrict the allowed method on a given `Resource`.
152
- * Curie syntax support for links (see http://tools.ietf.org/html/draft-kelly-json-hal-03#section-8.2)
153
- * Profile support for links
154
-
155
-
156
- ## Contributing
157
-
158
- * [List of hyperclient contributors][contributors]
159
-
160
- * Fork the project.
161
- * Make your feature addition or bug fix.
162
- * Add specs for it. This is important so we don't break it in a future
163
- version unintentionally.
164
- * Commit, do not mess with rakefile, version, or history.
165
- If you want to have your own version, that is fine but bump version
166
- in a commit by itself I can ignore when I pull.
167
- * Send me a pull request. Bonus points for topic branches.
168
-
169
- ## License
170
-
171
- MIT License. Copyright 2012 [Codegram Technologies][codegram]
172
-
173
- [hal]: http://stateless.co/hal_specification.html
174
- [contributors]: https://github.com/codegram/hyperclient/contributors
175
- [codegram]: http://codegram.com
176
- [documentup]: http://codegram.github.com/hyperclient
177
- [faraday]: http://github.com/lostisland/faraday
178
- [examples]: http://github.com/codegram/hyperclient/tree/master/examples
179
- [enumerable]: http://ruby-doc.org/core-1.9.3/Enumerable.html
180
- [rdoc]: http://rubydoc.org/github/codegram/hyperclient/master/frames
@@ -1,76 +0,0 @@
1
- require 'hyperclient'
2
-
3
- class Cyberscore
4
- include Hyperclient
5
-
6
- def news
7
- client.links.submissions.embedded.news
8
- end
9
-
10
- def submissions
11
- client.links..submissions.embedded.submissions
12
- end
13
-
14
- def games
15
- client.links.games.embedded.games
16
- end
17
-
18
- def add_game(name)
19
- client.links.submissions.post({name: name})
20
- end
21
-
22
- def motd
23
- client.attributes.motd
24
- end
25
-
26
- def method_missing(method, *args, &block)
27
- if client.respond_to?(method)
28
- client.send(method, *args, &block)
29
- else
30
- super
31
- end
32
- end
33
-
34
- private
35
- def client
36
- @client ||= Hyperclient::EntryPoint.new 'http://cs-api.heroku.com/api',
37
- {debug: false, headers: {'content-type' => 'application/json'}}
38
- end
39
- end
40
-
41
- def print_links(links)
42
- links.each do |name, link|
43
- if link.is_a?(Array)
44
- print_links(link)
45
- else
46
- puts %{Found "#{name}" at "#{link.url}" }
47
- end
48
- end
49
- end
50
-
51
- def print_games(games)
52
- games.each do |game|
53
- puts %{Found "#{game.attributes['name']}" }
54
- end
55
- end
56
-
57
-
58
- api = Cyberscore.new
59
-
60
- puts "Let's inspect the API:"
61
- puts "\n"
62
-
63
- puts 'Links from the entry point:'
64
- print_links(api.links)
65
- puts "\n"
66
-
67
- puts 'How is the server feeling today?'
68
- puts api.motd
69
- puts "\n"
70
-
71
- puts "Let's read the news:"
72
- print_links(api.links.news.links)
73
- puts "\n"
74
-
75
- puts "I like games!"
76
- print_games(api.games)
data/examples/hal_shop.rb DELETED
@@ -1,53 +0,0 @@
1
- require 'hyperclient'
2
- require 'pp'
3
-
4
- def print_resources(resources)
5
- resources.each do |name, resource|
6
- begin
7
- puts %{Found #{name} at #{resource.url}}
8
- rescue
9
- puts %{Found #{name}}
10
- end
11
- end
12
- end
13
-
14
- def print_attributes(attributes)
15
- puts "-----------------------------"
16
- attributes.each do |attribute, value|
17
- puts %{#{attribute}: #{value}}
18
- end
19
- end
20
-
21
- api = Hyperclient::EntryPoint.new 'http://hal-shop.heroku.com'
22
-
23
- puts "Let's inspect the API:"
24
- puts "\n"
25
-
26
- puts 'Links from the entry point:'
27
-
28
- print_resources(api.links)
29
-
30
- puts
31
- puts "Let's see what stats we have:"
32
- print_attributes(api.embedded.stats.attributes)
33
-
34
- products = api.links["http://hal-shop.heroku.com/rels/products"].resource
35
-
36
- puts
37
- puts "And what's the inventory of products?"
38
- puts products.attributes['inventory_size']
39
-
40
- puts
41
- puts 'What embedded resources does products have?'
42
- products.embedded.products.each do |product|
43
- puts 'Product:'
44
- print_attributes(product.attributes)
45
- puts
46
- end
47
-
48
- puts 'And links?'
49
- print_resources(products.links)
50
-
51
- puts
52
- puts 'Attributes of the first product?'
53
- print_attributes(products.embedded.products.first.attributes)
@@ -1,85 +0,0 @@
1
- require 'faraday'
2
- require 'net/http/digest_auth'
3
-
4
- module Faraday
5
- # Public: A Faraday middleware to use digest authentication. Since order of
6
- # middlewares do care, it should be the first one of the Request middlewares
7
- # in order to work properly (due to how digest authentication works).
8
- #
9
- # If some requests using the connection don't need to use digest auth you
10
- # don't have to worry, the middleware will do nothing.
11
- #
12
- # It uses Net::HTTP::DigestAuth to generate the authorization header but it
13
- # should work with any adapter.
14
- #
15
- # Examples:
16
- #
17
- # connection = Faraday.new(...) do |connection|
18
- # connection.request :digest, USER, PASSWORD
19
- # end
20
- #
21
- # # You can also use it later with a connection:
22
- # connection.digest_auth('USER', 'PASSWORD')
23
- #
24
- class Request::DigestAuth < Faraday::Middleware
25
-
26
- # Public: Initializes a DigestAuth.
27
- #
28
- # app - The Faraday app.
29
- # user - A String with the user to authentication the connection.
30
- # password - A String with the password to authentication the connection.
31
- def initialize(app, user, password)
32
- super(app)
33
- @user, @password = user, password
34
- end
35
-
36
- # Public: Sends a first request with an empty body to get the
37
- # authentication headers and then send the same request with the body and
38
- # authorization header.
39
- #
40
- # env - A Hash with the request environment.
41
- #
42
- # Returns a Faraday::Response.
43
- def call(env)
44
- response = handshake(env)
45
- return response unless response.status == 401
46
-
47
- env[:request_headers]['Authorization'] = header(response)
48
- @app.call(env)
49
- end
50
-
51
- private
52
- # Internal: Sends the the request with an empry body.
53
- #
54
- # env - A Hash with the request environment.
55
- #
56
- # Returns a Faraday::Response.
57
- def handshake(env)
58
- env_without_body = env.dup
59
- env_without_body.delete(:body)
60
-
61
- @app.call(env_without_body)
62
- end
63
-
64
- # Internal: Builds the authorization header with the authentication data.
65
- #
66
- # response - A Faraday::Response with the authenticate headers.
67
- #
68
- # Returns a String with the DigestAuth header.
69
- def header(response)
70
- uri = response.env[:url]
71
- uri.user = @user
72
- uri.password = @password
73
-
74
- realm = response.headers['www-authenticate']
75
- method = response.env[:method].to_s.upcase
76
-
77
- Net::HTTP::DigestAuth.new.auth_header(uri, realm, method)
78
- end
79
- end
80
- end
81
-
82
- # Register the middleware as a Request middleware with the name :digest
83
- registry = [Faraday, Faraday::Middleware].find{|mod| mod.respond_to?(:register_middleware)}
84
- raise "Could not find method register_middleware on Faraday or Faraday::Middleware" unless registry
85
- registry.register_middleware :request, digest: Faraday::Request::DigestAuth