totter 0.2.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. data/.gitignore +17 -0
  2. data/.travis.yml +4 -0
  3. data/Contributing.markdown +19 -0
  4. data/Gemfile +22 -0
  5. data/LICENSE +22 -0
  6. data/Rakefile +21 -0
  7. data/Readme.markdown +49 -0
  8. data/lib/totter.rb +26 -0
  9. data/lib/totter/client.rb +152 -0
  10. data/lib/totter/client/choices.rb +74 -0
  11. data/lib/totter/client/decisions.rb +91 -0
  12. data/lib/totter/client/slugs.rb +19 -0
  13. data/lib/totter/client/timelines.rb +16 -0
  14. data/lib/totter/client/users.rb +54 -0
  15. data/lib/totter/client/votes.rb +25 -0
  16. data/lib/totter/error.rb +51 -0
  17. data/lib/totter/version.rb +4 -0
  18. data/test/cassettes/choices/create_choice_upload.yml +85 -0
  19. data/test/cassettes/choices/create_for_image.yml +87 -0
  20. data/test/cassettes/choices/destroy.yml +122 -0
  21. data/test/cassettes/choices/show.yml +42 -0
  22. data/test/cassettes/decisions/analytics.yml +85 -0
  23. data/test/cassettes/decisions/create.yml +44 -0
  24. data/test/cassettes/decisions/destroy.yml +81 -0
  25. data/test/cassettes/decisions/flag.yml +81 -0
  26. data/test/cassettes/decisions/publish.yml +129 -0
  27. data/test/cassettes/decisions/show.yml +84 -0
  28. data/test/cassettes/decisions/unflag.yml +122 -0
  29. data/test/cassettes/slugs/show.yml +75 -0
  30. data/test/cassettes/timelines/global.yml +165 -0
  31. data/test/cassettes/users/following.yml +194 -0
  32. data/test/cassettes/users/me.yml +43 -0
  33. data/test/cassettes/users/user.yml +49 -0
  34. data/test/cassettes/votes/create.yml +96 -0
  35. data/test/support/client_macros.rb +5 -0
  36. data/test/test_helper.rb +24 -0
  37. data/test/totter/client/choices_test.rb +48 -0
  38. data/test/totter/client/decisions_test.rb +77 -0
  39. data/test/totter/client/slugs_test.rb +11 -0
  40. data/test/totter/client/timelines_test.rb +9 -0
  41. data/test/totter/client/users_test.rb +36 -0
  42. data/test/totter/client/votes_test.rb +15 -0
  43. data/test/totter/client_test.rb +31 -0
  44. data/test/totter_test.rb +17 -0
  45. data/totter.gemspec +24 -0
  46. metadata +155 -0
@@ -0,0 +1,19 @@
1
+ module Totter
2
+ class Client
3
+ # Client methods for working with slugs
4
+ module Slugs
5
+ # Get a slug.
6
+ #
7
+ # @param id [String] the slug id
8
+ # @param unique_id [String] an optional tracking string
9
+ # @return [Hashie::Mash]
10
+ # @example
11
+ # Seesaw.slug('d/3I0n0g')
12
+ def slug(id, unique_id = nil)
13
+ path = "slugs/#{id}"
14
+ path += "?unique_id=#{unique_id}" if unique_id
15
+ get path
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ module Totter
2
+ class Client
3
+ # Client methods for working with timelines
4
+ module Timelines
5
+ # Get recent decisions from the global timeline.
6
+ #
7
+ # @param limit [Fixnum] Number of decisions to return.
8
+ # @return [Array]
9
+ # @example
10
+ # Seesaw.recent_decisions
11
+ def global_timeline(limit = 10)
12
+ get "timelines/global?limit=#{limit}"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ module Totter
2
+ class Client
3
+ # Client methods for working with users
4
+ module Users
5
+ # Get the current user
6
+ #
7
+ # Requires authenticatied client.
8
+ #
9
+ # @return [Hashie::Mash]
10
+ # @see Totter::Client
11
+ # @example
12
+ # client.me
13
+ def me
14
+ get 'me'
15
+ end
16
+
17
+ # Get a single user
18
+ #
19
+ # @param user [String] A Seeaw username or ID.
20
+ # @return [Hashie::Mash]
21
+ # @example
22
+ # Seesaw.user('soffes')
23
+ def user(user)
24
+ get "users/#{user}"
25
+ end
26
+
27
+ # Follow a user.
28
+ #
29
+ # Requires authenticatied client.
30
+ #
31
+ # @param user [String] Username or ID of the user to follow.
32
+ # @return [Boolean] True if follow was successful, false otherwise.
33
+ # @see Totter::Client
34
+ # @example
35
+ # client.follow('gotwalt')
36
+ def follow(user)
37
+ boolean_from_response :post, "users/#{user}/follow"
38
+ end
39
+
40
+ # Unfollow a user.
41
+ #
42
+ # Requires authenticatied client.
43
+ #
44
+ # @param user [String] Username or ID of the user to unfollow.
45
+ # @return [Boolean] True if unfollow was successful, false otherwise.
46
+ # @see Totter::Client
47
+ # @example
48
+ # client.unfollow('kyle')
49
+ def unfollow(user)
50
+ boolean_from_response :post, "users/#{user}/unfollow"
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,25 @@
1
+ module Totter
2
+ class Client
3
+ # Client methods for working with votes
4
+ module Votes
5
+ # Create a vote.
6
+ #
7
+ # @param decision_user_id [Fixnum] the decision's owner's ID
8
+ # @param decision_id [Fixnum] the decision's ID
9
+ # @param choice_id [Fixnum] the choice's ID
10
+ # @param options [Hash] specifiy `:unique_id` or `:invitation_slug`
11
+ def create_vote(decision_user_id, decision_id, choice_id, options = {})
12
+ unique_id = options[:unique_id]
13
+ raise UniqueIDRequired unless unique_id or self.authenticated?
14
+
15
+ path = "users/#{decision_user_id}/decisions/#{decision_id}/votes"
16
+ params = { choice_id: choice_id, unique_id: unique_id }
17
+
18
+ slug = options[:invitation_slug]
19
+ params[:invitation] = { slug: slug } if slug and slug[0] == 'i'
20
+
21
+ post path, params
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,51 @@
1
+ module Totter
2
+ # Standard Totter error
3
+ class Error < StandardError; end
4
+
5
+ # Raised when Totter returns a 400 HTTP status code
6
+ class BadRequest < Error; end
7
+
8
+ # Raised when Totter returns a 401 HTTP status code
9
+ class Unauthorized < Error; end
10
+
11
+ # Raised when Totter returns a 403 HTTP status code
12
+ class Forbidden < Error; end
13
+
14
+ # Raised when Totter returns a 404 HTTP status code
15
+ class NotFound < Error; end
16
+
17
+ # Raised when Totter returns a 406 HTTP status code
18
+ class NotAcceptable < Error; end
19
+
20
+ # Raised when Totter returns a 422 HTTP status code
21
+ class UnprocessableEntity < Error; end
22
+
23
+ # Raised when Totter returns a 500 HTTP status code
24
+ class InternalServerError < Error; end
25
+
26
+ # Raised when Totter returns a 501 HTTP status code
27
+ class NotImplemented < Error; end
28
+
29
+ # Raised when Totter returns a 502 HTTP status code
30
+ class BadGateway < Error; end
31
+
32
+ # Raised when Totter returns a 503 HTTP status code
33
+ class ServiceUnavailable < Error; end
34
+
35
+ # Raised when a unique ID is required but not provided
36
+ class UniqueIDRequired < Error; end
37
+
38
+ # Status code to exception map
39
+ ERROR_MAP = {
40
+ 400 => Totter::BadRequest,
41
+ 401 => Totter::Unauthorized,
42
+ 403 => Totter::Forbidden,
43
+ 404 => Totter::NotFound,
44
+ 406 => Totter::NotAcceptable,
45
+ 422 => Totter::UnprocessableEntity,
46
+ 500 => Totter::InternalServerError,
47
+ 501 => Totter::NotImplemented,
48
+ 502 => Totter::BadGateway,
49
+ 503 => Totter::ServiceUnavailable
50
+ }
51
+ end
@@ -0,0 +1,4 @@
1
+ module Totter
2
+ # Verion of the Totter gem
3
+ VERSION = '0.2.0'
4
+ end
@@ -0,0 +1,85 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://localhost:5000/v1/users/1/decisions
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - Ruby
14
+ Authorization:
15
+ - Bearer 9774e653f7b3c1de5f21b61adc08ba24
16
+ Content-Type:
17
+ - application/json
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Content-Type:
24
+ - application/json; charset=utf-8
25
+ X-Ua-Compatible:
26
+ - IE=Edge
27
+ Etag:
28
+ - ! '"fe72872af6d81e7ab492d6b1ee9e2abd"'
29
+ Cache-Control:
30
+ - max-age=0, private, must-revalidate
31
+ X-Request-Id:
32
+ - a82f122c9397d644523d410f90be50c7
33
+ X-Runtime:
34
+ - '0.027279'
35
+ Connection:
36
+ - close
37
+ Server:
38
+ - thin 1.5.0 codename Knife
39
+ body:
40
+ encoding: US-ASCII
41
+ string: ! '{"created_at":"2013-01-30T21:44:41Z","final_vote_id":null,"flag_count":null,"id":32,"is_private":false,"meta":null,"published_at":null,"question":null,"updated_at":"2013-01-30T21:44:41Z","user_id":1,"pusher_channel":"decision-1-32","timeline_key":"1,32","analytics":{"views":0,"unique_viewers":0,"referrers":{},"votes":{},"total_votes":0},"user_vote":null,"choices":[],"invitations":[],"user":{"biography":null,"created_at":"2013-01-23T03:22:06Z","family_name":null,"given_name":null,"id":1,"meta":null,"moderated_decisions_count":null,"updated_at":"2013-01-23T03:22:06Z","username":null,"website":null,"avatar_url":"https://recess-dev.s3.amazonaws.com/default_avatars/v1/photo_1.png","full_name":"1","short_name":"1","display_name":"1","short_display_name":"1","analytics":{"votes":0,"decisions":0,"followers":0,"following":0}},"slug":"d/2r2v2A"}'
42
+ http_version:
43
+ recorded_at: Wed, 30 Jan 2013 21:44:41 GMT
44
+ - request:
45
+ method: post
46
+ uri: http://localhost:5000/v1/users/1/decisions/32/choices
47
+ body:
48
+ encoding: US-ASCII
49
+ string: ''
50
+ headers:
51
+ Accept:
52
+ - ! '*/*'
53
+ User-Agent:
54
+ - Ruby
55
+ Authorization:
56
+ - Bearer 9774e653f7b3c1de5f21b61adc08ba24
57
+ Content-Type:
58
+ - application/json
59
+ response:
60
+ status:
61
+ code: 200
62
+ message: OK
63
+ headers:
64
+ Content-Type:
65
+ - application/json; charset=utf-8
66
+ X-Ua-Compatible:
67
+ - IE=Edge
68
+ Etag:
69
+ - ! '"02b23992abdf817ee5c383ca29056d3b"'
70
+ Cache-Control:
71
+ - max-age=0, private, must-revalidate
72
+ X-Request-Id:
73
+ - 0666dd6a3a6bcbfa11b75f33fab2c63c
74
+ X-Runtime:
75
+ - '0.022490'
76
+ Connection:
77
+ - close
78
+ Server:
79
+ - thin 1.5.0 codename Knife
80
+ body:
81
+ encoding: US-ASCII
82
+ string: ! '{"created_at":"2013-01-30T21:44:41Z","decision_id":32,"decision_user_id":1,"id":19,"meta":null,"position":1,"subject":null,"type":"ImageChoice","updated_at":"2013-01-30T21:44:41Z","image_uri":"https://s3.amazonaws.com/","upload":{"url":"https://recess-dev.s3.amazonaws.com/","params":{"AWSAccessKeyId":"AKIAIYAL2IUDRW6PBPUQ","key":"gotwalt-pro.sf.gotwalt.com/decisions/32/19/1359582281/${filename}","policy":"eyJleHBpcmF0aW9uIjoiMjAxMy0wMS0zMFQyMjo0NDo0MVoiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJyZWNlc3MtZGV2In0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCJnb3R3YWx0LXByby5zZi5nb3R3YWx0LmNvbS9kZWNpc2lvbnMvMzIvMTkvMTM1OTU4MjI4MS8iXSx7ImFjbCI6InB1YmxpYy1yZWFkIn0seyJzdWNjZXNzX2FjdGlvbl9yZWRpcmVjdCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC92MS91c2Vycy8xL2RlY2lzaW9ucy8zMi9jaG9pY2VzLzMwNDAybzBMMTgyZjJGMTYzMC9zMyJ9LFsiY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3Nl1dfQ==","signature":"2Sgsgg8nWp2A7FP6fG0EEN6MztY=","acl":"public-read","success_action_redirect":"http://localhost:5000/v1/users/1/decisions/32/choices/30402o0L182f2F1630/s3"}}}'
83
+ http_version:
84
+ recorded_at: Wed, 30 Jan 2013 21:44:41 GMT
85
+ recorded_with: VCR 2.4.0
@@ -0,0 +1,87 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://localhost:5000/v1/users/1/decisions
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - Ruby
14
+ Authorization:
15
+ - Bearer 9774e653f7b3c1de5f21b61adc08ba24
16
+ Content-Type:
17
+ - application/json
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Content-Type:
24
+ - application/json; charset=utf-8
25
+ X-Ua-Compatible:
26
+ - IE=Edge
27
+ Etag:
28
+ - ! '"17c9b6356fae36d9b359dd0e2e56915f"'
29
+ Cache-Control:
30
+ - max-age=0, private, must-revalidate
31
+ X-Request-Id:
32
+ - fddf25eccf2dea50779bcc1268429bea
33
+ X-Runtime:
34
+ - '0.075714'
35
+ Connection:
36
+ - close
37
+ Server:
38
+ - thin 1.5.0 codename Knife
39
+ body:
40
+ encoding: US-ASCII
41
+ string: ! '{"created_at":"2013-01-30T21:44:41Z","final_vote_id":null,"flag_count":null,"id":33,"is_private":false,"meta":null,"published_at":null,"question":null,"updated_at":"2013-01-30T21:44:41Z","user_id":1,"pusher_channel":"decision-1-33","timeline_key":"1,33","analytics":{"views":0,"unique_viewers":0,"referrers":{},"votes":{},"total_votes":0},"user_vote":null,"choices":[],"invitations":[],"user":{"biography":null,"created_at":"2013-01-23T03:22:06Z","family_name":null,"given_name":null,"id":1,"meta":null,"moderated_decisions_count":null,"updated_at":"2013-01-23T03:22:06Z","username":null,"website":null,"avatar_url":"https://recess-dev.s3.amazonaws.com/default_avatars/v1/photo_1.png","full_name":"1","short_name":"1","display_name":"1","short_display_name":"1","analytics":{"votes":0,"decisions":0,"followers":0,"following":0}},"slug":"d/1W362T"}'
42
+ http_version:
43
+ recorded_at: Wed, 30 Jan 2013 21:44:41 GMT
44
+ - request:
45
+ method: post
46
+ uri: http://localhost:5000/v1/users/1/decisions/33/choices
47
+ body:
48
+ encoding: UTF-8
49
+ string: ! '{"choice":{"type":"image","image_url":"http://recess.s3.amazonaws.com/default_avatars/v1/photo_1.png","subject":"Test
50
+ Image","meta":{"link_url":"http://seesaw.co","link_title":"Seesaw"}}}'
51
+ headers:
52
+ Accept:
53
+ - ! '*/*'
54
+ User-Agent:
55
+ - Ruby
56
+ Authorization:
57
+ - Bearer 9774e653f7b3c1de5f21b61adc08ba24
58
+ Content-Type:
59
+ - application/json
60
+ response:
61
+ status:
62
+ code: 200
63
+ message: OK
64
+ headers:
65
+ Content-Type:
66
+ - application/json; charset=utf-8
67
+ X-Ua-Compatible:
68
+ - IE=Edge
69
+ Etag:
70
+ - ! '"6bd2e538cb6c096628df5e5e8c52b8bb"'
71
+ Cache-Control:
72
+ - max-age=0, private, must-revalidate
73
+ X-Request-Id:
74
+ - 6cab0f1f8d22dedc4920106aed2852ff
75
+ X-Runtime:
76
+ - '0.604433'
77
+ Connection:
78
+ - close
79
+ Server:
80
+ - thin 1.5.0 codename Knife
81
+ body:
82
+ encoding: US-ASCII
83
+ string: ! '{"created_at":"2013-01-30T21:44:41Z","decision_id":33,"decision_user_id":1,"id":20,"meta":{"link_url":"http://seesaw.co","link_title":"Seesaw"},"position":1,"subject":"Test
84
+ Image","type":"ImageChoice","updated_at":"2013-01-30T21:44:41Z","image_uri":"https://recess-dev.s3.amazonaws.com/gotwalt-pro.sf.gotwalt.com/decisions/33/20/1359582281/photo.png"}'
85
+ http_version:
86
+ recorded_at: Wed, 30 Jan 2013 21:44:41 GMT
87
+ recorded_with: VCR 2.4.0
@@ -0,0 +1,122 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://localhost:5000/v1/users/1/decisions
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - Ruby
14
+ Authorization:
15
+ - Bearer 9774e653f7b3c1de5f21b61adc08ba24
16
+ Content-Type:
17
+ - application/json
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Content-Type:
24
+ - application/json; charset=utf-8
25
+ X-Ua-Compatible:
26
+ - IE=Edge
27
+ Etag:
28
+ - ! '"a065c212f634cce169159f9e66c40e42"'
29
+ Cache-Control:
30
+ - max-age=0, private, must-revalidate
31
+ X-Request-Id:
32
+ - 11b81d00325361beeb6dda08b5eca88d
33
+ X-Runtime:
34
+ - '0.027600'
35
+ Connection:
36
+ - close
37
+ Server:
38
+ - thin 1.5.0 codename Knife
39
+ body:
40
+ encoding: US-ASCII
41
+ string: ! '{"created_at":"2013-01-30T21:45:41Z","final_vote_id":null,"flag_count":null,"id":34,"is_private":false,"meta":null,"published_at":null,"question":null,"updated_at":"2013-01-30T21:45:41Z","user_id":1,"pusher_channel":"decision-1-34","timeline_key":"1,34","analytics":{"views":0,"unique_viewers":0,"referrers":{},"votes":{},"total_votes":0},"user_vote":null,"choices":[],"invitations":[],"user":{"biography":null,"created_at":"2013-01-23T03:22:06Z","family_name":null,"given_name":null,"id":1,"meta":null,"moderated_decisions_count":null,"updated_at":"2013-01-23T03:22:06Z","username":null,"website":null,"avatar_url":"https://recess-dev.s3.amazonaws.com/default_avatars/v1/photo_1.png","full_name":"1","short_name":"1","display_name":"1","short_display_name":"1","analytics":{"votes":0,"decisions":0,"followers":0,"following":0}},"slug":"d/3H2Y0T"}'
42
+ http_version:
43
+ recorded_at: Wed, 30 Jan 2013 21:45:42 GMT
44
+ - request:
45
+ method: post
46
+ uri: http://localhost:5000/v1/users/1/decisions/34/choices
47
+ body:
48
+ encoding: US-ASCII
49
+ string: ''
50
+ headers:
51
+ Accept:
52
+ - ! '*/*'
53
+ User-Agent:
54
+ - Ruby
55
+ Authorization:
56
+ - Bearer 9774e653f7b3c1de5f21b61adc08ba24
57
+ Content-Type:
58
+ - application/json
59
+ response:
60
+ status:
61
+ code: 200
62
+ message: OK
63
+ headers:
64
+ Content-Type:
65
+ - application/json; charset=utf-8
66
+ X-Ua-Compatible:
67
+ - IE=Edge
68
+ Etag:
69
+ - ! '"ee3e37e9de385d6218a89aa990e974a7"'
70
+ Cache-Control:
71
+ - max-age=0, private, must-revalidate
72
+ X-Request-Id:
73
+ - d89c73e6a43d0a2deb90538b92533b0f
74
+ X-Runtime:
75
+ - '0.021898'
76
+ Connection:
77
+ - close
78
+ Server:
79
+ - thin 1.5.0 codename Knife
80
+ body:
81
+ encoding: US-ASCII
82
+ string: ! '{"created_at":"2013-01-30T21:45:42Z","decision_id":34,"decision_user_id":1,"id":21,"meta":null,"position":1,"subject":null,"type":"ImageChoice","updated_at":"2013-01-30T21:45:42Z","image_uri":"https://s3.amazonaws.com/","upload":{"url":"https://recess-dev.s3.amazonaws.com/","params":{"AWSAccessKeyId":"AKIAIYAL2IUDRW6PBPUQ","key":"gotwalt-pro.sf.gotwalt.com/decisions/34/21/1359582342/${filename}","policy":"eyJleHBpcmF0aW9uIjoiMjAxMy0wMS0zMFQyMjo0NTo0MloiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJyZWNlc3MtZGV2In0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCJnb3R3YWx0LXByby5zZi5nb3R3YWx0LmNvbS9kZWNpc2lvbnMvMzQvMjEvMTM1OTU4MjM0Mi8iXSx7ImFjbCI6InB1YmxpYy1yZWFkIn0seyJzdWNjZXNzX2FjdGlvbl9yZWRpcmVjdCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC92MS91c2Vycy8xL2RlY2lzaW9ucy8zNC9jaG9pY2VzLzN6MzgzRDJwM2szajJEMkkwVi9zMyJ9LFsiY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3Nl1dfQ==","signature":"L+fuJLNpquy1z/dQgkDFanvhEWY=","acl":"public-read","success_action_redirect":"http://localhost:5000/v1/users/1/decisions/34/choices/3z383D2p3k3j2D2I0V/s3"}}}'
83
+ http_version:
84
+ recorded_at: Wed, 30 Jan 2013 21:45:42 GMT
85
+ - request:
86
+ method: delete
87
+ uri: http://localhost:5000/v1/users/1/decisions/34/choices/21
88
+ body:
89
+ encoding: US-ASCII
90
+ string: ''
91
+ headers:
92
+ Accept:
93
+ - ! '*/*'
94
+ User-Agent:
95
+ - Ruby
96
+ Authorization:
97
+ - Bearer 9774e653f7b3c1de5f21b61adc08ba24
98
+ Content-Type:
99
+ - application/json
100
+ response:
101
+ status:
102
+ code: 204
103
+ message: No Content
104
+ headers:
105
+ X-Ua-Compatible:
106
+ - IE=Edge
107
+ Cache-Control:
108
+ - no-cache
109
+ X-Request-Id:
110
+ - a7961b4c7ba620f19eeab109ac8b2378
111
+ X-Runtime:
112
+ - '0.013544'
113
+ Connection:
114
+ - close
115
+ Server:
116
+ - thin 1.5.0 codename Knife
117
+ body:
118
+ encoding: US-ASCII
119
+ string: ''
120
+ http_version:
121
+ recorded_at: Wed, 30 Jan 2013 21:45:42 GMT
122
+ recorded_with: VCR 2.4.0