taskrabbit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.gitignore +6 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +22 -0
  4. data/Guardfile +8 -0
  5. data/README.md +132 -0
  6. data/Rakefile +53 -0
  7. data/lib/taskrabbit.rb +21 -0
  8. data/lib/taskrabbit/account.rb +7 -0
  9. data/lib/taskrabbit/api.rb +47 -0
  10. data/lib/taskrabbit/association.rb +52 -0
  11. data/lib/taskrabbit/city.rb +19 -0
  12. data/lib/taskrabbit/client.rb +47 -0
  13. data/lib/taskrabbit/collection.rb +17 -0
  14. data/lib/taskrabbit/config.rb +43 -0
  15. data/lib/taskrabbit/error.rb +10 -0
  16. data/lib/taskrabbit/location.rb +19 -0
  17. data/lib/taskrabbit/proxy.rb +62 -0
  18. data/lib/taskrabbit/smash.rb +82 -0
  19. data/lib/taskrabbit/task.rb +54 -0
  20. data/lib/taskrabbit/transformer.rb +5 -0
  21. data/lib/taskrabbit/user.rb +26 -0
  22. data/lib/taskrabbit/version.rb +3 -0
  23. data/spec/spec_helper.rb +33 -0
  24. data/spec/support/cassettes/account/no_user.yml +30 -0
  25. data/spec/support/cassettes/account/properties.yml +32 -0
  26. data/spec/support/cassettes/account/tasks.yml +63 -0
  27. data/spec/support/cassettes/account/with_user.yml +32 -0
  28. data/spec/support/cassettes/cities/all.yml +32 -0
  29. data/spec/support/cassettes/cities/find.yml +32 -0
  30. data/spec/support/cassettes/cities/properties.yml +32 -0
  31. data/spec/support/cassettes/errors/404.yml +362 -0
  32. data/spec/support/cassettes/locations/properties.yml +63 -0
  33. data/spec/support/cassettes/tasks/all.yml +32 -0
  34. data/spec/support/cassettes/tasks/create/default.yml +30 -0
  35. data/spec/support/cassettes/tasks/create/using_account.yml +30 -0
  36. data/spec/support/cassettes/tasks/create/with_location.yml +32 -0
  37. data/spec/support/cassettes/tasks/create/without_credit_card.yml +30 -0
  38. data/spec/support/cassettes/tasks/create/without_user.yml +30 -0
  39. data/spec/support/cassettes/tasks/delete.yml +63 -0
  40. data/spec/support/cassettes/tasks/find.yml +32 -0
  41. data/spec/support/cassettes/tasks/properties.yml +32 -0
  42. data/spec/support/cassettes/tasks/save.yml +63 -0
  43. data/spec/support/cassettes/tasks/update.yml +63 -0
  44. data/spec/support/cassettes/tasks/without_client.yml +30 -0
  45. data/spec/support/cassettes/users/find.yml +32 -0
  46. data/spec/support/cassettes/users/properties.yml +32 -0
  47. data/spec/support/cassettes/users/tasks/all.yml +32 -0
  48. data/spec/taskrabbit/account_spec.rb +65 -0
  49. data/spec/taskrabbit/api_spec.rb +34 -0
  50. data/spec/taskrabbit/city_spec.rb +61 -0
  51. data/spec/taskrabbit/collection_spec.rb +17 -0
  52. data/spec/taskrabbit/error_spec.rb +13 -0
  53. data/spec/taskrabbit/location_spec.rb +26 -0
  54. data/spec/taskrabbit/proxy_spec.rb +23 -0
  55. data/spec/taskrabbit/smash_spec.rb +129 -0
  56. data/spec/taskrabbit/task_spec.rb +235 -0
  57. data/spec/taskrabbit/taskrabbit_spec.rb +31 -0
  58. data/spec/taskrabbit/user_spec.rb +70 -0
  59. data/taskrabbit.gemspec +26 -0
  60. metadata +194 -0
@@ -0,0 +1,43 @@
1
+ module Taskrabbit
2
+ module Config
3
+ DEFAULT_BASE_URI = 'http://www.taskrabbit.com'
4
+ DEFAULT_END_POINT = 'api/v1'
5
+ DEFAULT_CLIENT_SECRET = nil
6
+
7
+ VALID_OPTIONS_KEYS = [
8
+ :base_uri,
9
+ :client_secret,
10
+ :endpoint
11
+ ]
12
+
13
+ attr_accessor *VALID_OPTIONS_KEYS
14
+
15
+ # When this module is extended, set all configuration options to their default values
16
+ def self.extended(base)
17
+ base.reset
18
+ end
19
+
20
+ # Convenience method to allow configuration options to be set in a block
21
+ def configure
22
+ yield self
23
+ self
24
+ end
25
+
26
+ # Create a hash of options and their values
27
+ def options
28
+ {}.tap do |options|
29
+ VALID_OPTIONS_KEYS.each{|k| options[k] = send(k)}
30
+ end
31
+ end
32
+
33
+ # Reset all configuration options to defaults
34
+ def reset
35
+ self.tap do |c|
36
+ c.base_uri = DEFAULT_BASE_URI
37
+ c.endpoint = DEFAULT_END_POINT
38
+ c.client_secret = DEFAULT_CLIENT_SECRET
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ module Taskrabbit
2
+ class Error < StandardError
3
+ attr_accessor :response
4
+
5
+ def initialize(message, response = {})
6
+ @response = response
7
+ super message
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ module Taskrabbit
2
+ class Location < Smash
3
+ property :id
4
+ property :name
5
+ property :address
6
+ property :approximate_radius
7
+ property :city
8
+ property :zip
9
+ property :partial
10
+ property :state
11
+ property :complete
12
+
13
+ class << self
14
+ def all(scope, options = {})
15
+ scope.request('get', scope.association_path(self), Api::collection_transformers[self], options)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,62 @@
1
+ class BasicObject #:nodoc:
2
+ instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|instance_eval|proxy_|^object_id$)/ }
3
+ end unless defined?(BasicObject)
4
+
5
+ module Taskrabbit
6
+ class Proxy < BasicObject
7
+
8
+ COLLECTION_DELEGATE = %w{first last count size length each keys links}.freeze
9
+
10
+ def initialize(api, target)
11
+ @api = api
12
+ @target = target
13
+ @opts = nil
14
+ end
15
+
16
+ def all(options = {})
17
+ proxy_found(options)
18
+ end
19
+
20
+ def new(options = {})
21
+ @target.new(options, @api)
22
+ end
23
+
24
+ def find(param, options={})
25
+ return all(options) if param == :all
26
+ return @target.find(@api, param) if @target.respond_to?(:find)
27
+ nil
28
+ end
29
+
30
+ COLLECTION_DELEGATE.each do |method|
31
+ define_method(method) do |*args, &block|
32
+ all(args.pop || {}).send(method, *args, &block)
33
+ end
34
+ end
35
+
36
+ def create(args)
37
+ @target.create(@api, args) if @target.respond_to?(:create)
38
+ end
39
+
40
+ protected
41
+
42
+ def proxy_found(options)
43
+ to_reload = options.delete(:reload)
44
+ return (@found = load_found(options)) if to_reload
45
+ # Check to see if options have changed
46
+ @found = load_found(options) unless @opts == options
47
+ @found
48
+ end
49
+
50
+ private
51
+
52
+ def method_missing(method, *args, &block)
53
+ @target.send(method, *args, &block)
54
+ end
55
+
56
+ def load_found(options)
57
+ @opts = options
58
+ @target.all(@api, @opts)
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,82 @@
1
+ module Taskrabbit
2
+ class Smash < APISmith::Smash
3
+ include Transformer
4
+ include Association
5
+ attr_accessor :api
6
+ attr_accessor :loaded
7
+
8
+ property :errors
9
+ property :links
10
+ property :error
11
+
12
+ class << self
13
+ def find(api, id)
14
+ raise Taskrabbit::Error.new("Couldn't find #{self} without an ID") if id.nil?
15
+ new({:id => id}, api)
16
+ end
17
+ end
18
+
19
+ class Error < Taskrabbit::Error
20
+ end
21
+
22
+ def initialize(options = {}, api = nil)
23
+ self.api = api
24
+ self.loaded = false
25
+ super options
26
+ end
27
+
28
+ # do a request through the api instance
29
+ def request(*args)
30
+ api.request *args
31
+ end
32
+
33
+ # check if the object is valid
34
+ def valid?
35
+ errors.nil? and error.nil?
36
+ end
37
+
38
+ def redirect_url
39
+ links["redirect"] if links
40
+ end
41
+
42
+ def redirect?
43
+ !!redirect_url
44
+ end
45
+
46
+ # reload the object after doing a query to the api
47
+ def reload(method, path, options = {})
48
+ self.loaded = true
49
+ response = request(method, path, self.class, options)
50
+ self.merge!(response)
51
+ clear_errors
52
+ !redirect?
53
+ rescue Smash::Error => e
54
+ self.merge!(e.response) if e.response.is_a?(Hash)
55
+ false
56
+ end
57
+
58
+ # fetch the object
59
+ def fetch; end
60
+
61
+ # get the property from the hash
62
+ # if the value is not set and the object has not been loaded, try to load it
63
+ def [](property)
64
+ value = nil
65
+ return value unless (value = super(property)).nil?
66
+ if api and !loaded
67
+ # load the object if trying to access a property
68
+ self.loaded = true
69
+ fetch
70
+ end
71
+ super(property)
72
+ end
73
+
74
+ private
75
+
76
+ # remove the errors from the object
77
+ def clear_errors
78
+ %w{error errors}.map { |k| self.delete(k) }
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,54 @@
1
+ module Taskrabbit
2
+ class Task < Smash
3
+ property :id
4
+ property :name
5
+ property :user, :transformer => User
6
+ property :runner, :transformer => User
7
+ property :runners, :transformer => Api::collection_transformers[User]
8
+ property :named_price
9
+ property :charge_price
10
+ property :cost_in_cents
11
+ property :links
12
+ property :state_label
13
+ property :city_id
14
+ property :city, :transformer => City
15
+ property :description, :default => ''
16
+ property :private_description, :default => ''
17
+ property :private_runner, :default => false
18
+ property :virtual, :default => false
19
+ property :state
20
+ property :complete_by_time, :transformer => TIME_TRANSFORMER
21
+ property :state_changed_at, :transformer => TIME_TRANSFORMER
22
+ property :assign_by_time, :transformer => TIME_TRANSFORMER
23
+ property :location_visits, :transformer => Api::collection_transformers[Location]
24
+ property :other_locations_attributes
25
+ property :uploaded_photos_attributes
26
+ property :uploaded_sounds_attributes
27
+
28
+ class << self
29
+ def all(scope, options = {})
30
+ scope.request('get', scope.association_path(self), Api::collection_transformers[self], options)
31
+ end
32
+
33
+ def create(api, params)
34
+ api.request('post', "tasks", self, :task => params)
35
+ end
36
+ end
37
+
38
+ def fetch
39
+ reload('get', "tasks/#{id.to_s}") unless id.nil?
40
+ end
41
+
42
+ def save
43
+ if id.nil?
44
+ reload('post', "tasks", :task => self.to_hash)
45
+ else
46
+ reload('put', "tasks/#{id.to_s}", self.to_hash)
47
+ end
48
+ end
49
+
50
+ def delete!
51
+ reload('delete', "tasks/#{id.to_s}")
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,5 @@
1
+ module Taskrabbit
2
+ module Transformer
3
+ TIME_TRANSFORMER = lambda { |v| Time.at(v.to_i) }
4
+ end
5
+ end
@@ -0,0 +1,26 @@
1
+ module Taskrabbit
2
+ class User < Smash
3
+ property :id
4
+ property :short_name
5
+ property :first_name
6
+ property :full_name
7
+ property :display_name
8
+ property :runner, :default => false
9
+ property :email
10
+ property :mobile_phone
11
+ property :home_phone
12
+ property :tasks, :transformer => Api::collection_transformers[Task]
13
+ property :city, :transformer => City
14
+ property :zip_code
15
+ property :locations, :transformer => Api::collection_transformers[Location]
16
+ property :links
17
+
18
+ has_many :tasks, Task, :on => lambda { |user| "users/#{user.id}/tasks" }
19
+ has_many :locations, Location, :on => lambda { |user| "users/#{user.id}/locations" }
20
+
21
+ def fetch
22
+ reload('get', "users/#{id.to_s}")
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Taskrabbit
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,33 @@
1
+ ENV["RAILS_ENV"] ||= 'test'
2
+
3
+ require 'rspec'
4
+ require 'bundler/setup'
5
+ require 'taskrabbit'
6
+
7
+
8
+ Bundler.setup
9
+ Bundler.require :default, :test
10
+
11
+ CASSETTES_PATH = File.join(File.dirname(__FILE__), "support", "cassettes")
12
+ TR_USERS = {
13
+ :with_card => {:secret => 'RhyRtRg1bRNyqmdozkY6JJJ3eGDpoRGTm9AXUudp', :id => 49720},
14
+ :without_card => {:secret => 'sjCuNHsxMRkFiJGpLWZzYJksDjfnXtDvDcPuuDkn', :id => 49719},
15
+ }
16
+
17
+ module Taskrabbit
18
+ module Config
19
+ remove_const(:DEFAULT_BASE_URI)
20
+ remove_const(:DEFAULT_CLIENT_SECRET)
21
+ DEFAULT_BASE_URI = 'http://localhost:3000'
22
+ DEFAULT_CLIENT_SECRET = 'euqmQpzV04GmN1dJTY639PdI7eiSjCjI3lKTkPWn'
23
+ end
24
+ end
25
+ Taskrabbit.reset
26
+
27
+ RSpec.configure do |config|
28
+ end
29
+
30
+ VCR.config do |c|
31
+ c.cassette_library_dir = CASSETTES_PATH
32
+ c.stub_with :fakeweb
33
+ end
@@ -0,0 +1,30 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://localhost:3000/api/v1/account?
6
+ body:
7
+ headers:
8
+ x-client-application:
9
+ - euqmQpzV04GmN1dJTY639PdI7eiSjCjI3lKTkPWn
10
+ authorization:
11
+ - OAuth
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 401
15
+ message: Unauthorized
16
+ headers:
17
+ content-type:
18
+ - application/json; charset=utf-8
19
+ x-runtime:
20
+ - "447"
21
+ server:
22
+ - WEBrick/1.3.1 (Ruby/1.8.7/2011-02-18)
23
+ date:
24
+ - Sat, 17 Mar 2012 23:12:08 GMT
25
+ content-length:
26
+ - "63"
27
+ cache-control:
28
+ - no-cache
29
+ body: "{\"error\":\"There must be an authenticated user for this action\"}"
30
+ http_version: "1.1"
@@ -0,0 +1,32 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://localhost:3000/api/v1/account?
6
+ body:
7
+ headers:
8
+ x-client-application:
9
+ - euqmQpzV04GmN1dJTY639PdI7eiSjCjI3lKTkPWn
10
+ authorization:
11
+ - OAuth RhyRtRg1bRNyqmdozkY6JJJ3eGDpoRGTm9AXUudp
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ etag:
18
+ - "\"1e7456943686e7860596b08fd8493a2b\""
19
+ content-type:
20
+ - application/json; charset=utf-8
21
+ x-runtime:
22
+ - "3518"
23
+ server:
24
+ - WEBrick/1.3.1 (Ruby/1.8.7/2011-02-18)
25
+ date:
26
+ - Sat, 17 Mar 2012 23:12:06 GMT
27
+ content-length:
28
+ - "2956"
29
+ cache-control:
30
+ - private, max-age=0, must-revalidate
31
+ body: "{\"city\":{\"name\":\"SF Bay Area\",\"lng\":-122.419416,\"id\":3,\"links\":{\"get\":\"/api/v1/cities/3\"},\"lat\":37.77493},\"zip_code\":\"64321\",\"id\":49720,\"tasks\":{\"items\":[{\"name\":\"My First Task\",\"city\":{\"name\":\"New York City\",\"lng\":-74.005973,\"id\":4,\"links\":{\"get\":\"/api/v1/cities/4\"},\"lat\":40.714353},\"charge_price\":20,\"private_runner\":false,\"named_price\":20,\"complete_by_time\":1332093600,\"id\":22673,\"state_changed_at\":1332025380,\"cost_in_cents\":0,\"links\":{\"html\":\"http://local.taskrabbit.com/tasks/my-first-task--47\",\"get\":\"/api/v1/tasks/22673\",\"delete\":\"/api/v1/tasks/22673\",\"put\":\"/api/v1/tasks/22673\",\"authenticated\":\"http://local.taskrabbit.com/go/2f249e87a04016d741f163fe991468737e367c8e334eb5d5a53a63d741ce0019ba1a9c33366a76cadc06bdcb9259c5549a44\"},\"runners\":{\"items\":[]},\"state_label\":\"posted\",\"assign_by_time\":1332082800,\"state\":\"opened\"},{\"name\":\"New Name\",\"city\":{\"name\":\"New York City\",\"lng\":-74.005973,\"id\":4,\"links\":{\"get\":\"/api/v1/cities/4\"},\"lat\":40.714353},\"charge_price\":20,\"private_runner\":false,\"named_price\":20,\"complete_by_time\":1332093600,\"id\":22674,\"state_changed_at\":1332025387,\"cost_in_cents\":0,\"links\":{\"html\":\"http://local.taskrabbit.com/tasks/new-name--3\",\"get\":\"/api/v1/tasks/22674\",\"delete\":\"/api/v1/tasks/22674\",\"put\":\"/api/v1/tasks/22674\",\"authenticated\":\"http://local.taskrabbit.com/go/459b5e05e7a6542891148717ed9cdd4a25fb5d5f71f094c098a93beb25ba26303c4ea5e2c8e01da3743703abbe1da5b46980\"},\"runners\":{\"items\":[]},\"state_label\":\"posted\",\"assign_by_time\":1332082800,\"state\":\"opened\"},{\"name\":\"My First Task\",\"city\":{\"name\":\"New York City\",\"lng\":-74.005973,\"id\":4,\"links\":{\"get\":\"/api/v1/cities/4\"},\"lat\":40.714353},\"charge_price\":20,\"private_runner\":false,\"named_price\":20,\"complete_by_time\":1332093600,\"id\":22675,\"state_changed_at\":1332025394,\"cost_in_cents\":0,\"links\":{\"html\":\"http://local.taskrabbit.com/tasks/my-first-task--49\",\"get\":\"/api/v1/tasks/22675\",\"delete\":\"/api/v1/tasks/22675\",\"put\":\"/api/v1/tasks/22675\",\"authenticated\":\"http://local.taskrabbit.com/go/a89862d84f6a3b8b3175c46bc824ba3c4086519395730898237d56ef90ad672e540e62370c6a87b6c6ec2f601c10e2486ba7\"},\"runners\":{\"items\":[]},\"state_label\":\"posted\",\"assign_by_time\":1332082800,\"state\":\"opened\"}],\"links\":{\"get\":\"/api/v1/users/49720/tasks\",\"last\":\"/api/v1/users/49720/tasks?page=1\",\"first\":\"/api/v1/users/49720/tasks?page=1\"}},\"short_name\":\"Bob\",\"full_name\":\"Bob Sponge\",\"last_name\":\"Sponge\",\"links\":{\"get\":\"/api/v1/users/49720\",\"avatar_url\":\"http://local.taskrabbit.com/images/default_avatars/poster_thumb.png\"},\"display_name\":\"Bob S.\",\"locations\":{\"items\":[{\"name\":\"Home\",\"city\":\"San Francisco\",\"approximate_radius\":0,\"address\":\"432 example\",\"zip\":\"94123\",\"partial\":\"example, San Francisco, Ca 94123\",\"id\":37439,\"lng\":2.108266,\"complete\":\"432 example, San Francisco, Ca 94123\",\"lat\":41.5512199,\"state\":\"Ca\"}],\"links\":{\"get\":\"/api/v1/users/49720/locations\"}},\"email\":\"bobsponge@example.com\",\"first_name\":\"Bob\",\"counts\":{\"posted_tasks\":30,\"active_tasks\":3,\"ongoing_tasks\":3}}"
32
+ http_version: "1.1"
@@ -0,0 +1,63 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://localhost:3000/api/v1/account?
6
+ body:
7
+ headers:
8
+ x-client-application:
9
+ - euqmQpzV04GmN1dJTY639PdI7eiSjCjI3lKTkPWn
10
+ authorization:
11
+ - OAuth RhyRtRg1bRNyqmdozkY6JJJ3eGDpoRGTm9AXUudp
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ etag:
18
+ - "\"1e7456943686e7860596b08fd8493a2b\""
19
+ content-type:
20
+ - application/json; charset=utf-8
21
+ x-runtime:
22
+ - "3887"
23
+ server:
24
+ - WEBrick/1.3.1 (Ruby/1.8.7/2011-02-18)
25
+ date:
26
+ - Sat, 17 Mar 2012 23:12:20 GMT
27
+ content-length:
28
+ - "2956"
29
+ cache-control:
30
+ - private, max-age=0, must-revalidate
31
+ body: "{\"city\":{\"name\":\"SF Bay Area\",\"lng\":-122.419416,\"id\":3,\"links\":{\"get\":\"/api/v1/cities/3\"},\"lat\":37.77493},\"zip_code\":\"64321\",\"id\":49720,\"tasks\":{\"items\":[{\"name\":\"My First Task\",\"city\":{\"name\":\"New York City\",\"lng\":-74.005973,\"id\":4,\"links\":{\"get\":\"/api/v1/cities/4\"},\"lat\":40.714353},\"charge_price\":20,\"private_runner\":false,\"named_price\":20,\"complete_by_time\":1332093600,\"id\":22673,\"state_changed_at\":1332025380,\"cost_in_cents\":0,\"links\":{\"html\":\"http://local.taskrabbit.com/tasks/my-first-task--47\",\"get\":\"/api/v1/tasks/22673\",\"delete\":\"/api/v1/tasks/22673\",\"put\":\"/api/v1/tasks/22673\",\"authenticated\":\"http://local.taskrabbit.com/go/2f249e87a04016d741f163fe991468737e367c8e334eb5d5a53a63d741ce0019ba1a9c33366a76cadc06bdcb9259c5549a44\"},\"runners\":{\"items\":[]},\"state_label\":\"posted\",\"assign_by_time\":1332082800,\"state\":\"opened\"},{\"name\":\"New Name\",\"city\":{\"name\":\"New York City\",\"lng\":-74.005973,\"id\":4,\"links\":{\"get\":\"/api/v1/cities/4\"},\"lat\":40.714353},\"charge_price\":20,\"private_runner\":false,\"named_price\":20,\"complete_by_time\":1332093600,\"id\":22674,\"state_changed_at\":1332025387,\"cost_in_cents\":0,\"links\":{\"html\":\"http://local.taskrabbit.com/tasks/new-name--3\",\"get\":\"/api/v1/tasks/22674\",\"delete\":\"/api/v1/tasks/22674\",\"put\":\"/api/v1/tasks/22674\",\"authenticated\":\"http://local.taskrabbit.com/go/459b5e05e7a6542891148717ed9cdd4a25fb5d5f71f094c098a93beb25ba26303c4ea5e2c8e01da3743703abbe1da5b46980\"},\"runners\":{\"items\":[]},\"state_label\":\"posted\",\"assign_by_time\":1332082800,\"state\":\"opened\"},{\"name\":\"My First Task\",\"city\":{\"name\":\"New York City\",\"lng\":-74.005973,\"id\":4,\"links\":{\"get\":\"/api/v1/cities/4\"},\"lat\":40.714353},\"charge_price\":20,\"private_runner\":false,\"named_price\":20,\"complete_by_time\":1332093600,\"id\":22675,\"state_changed_at\":1332025394,\"cost_in_cents\":0,\"links\":{\"html\":\"http://local.taskrabbit.com/tasks/my-first-task--49\",\"get\":\"/api/v1/tasks/22675\",\"delete\":\"/api/v1/tasks/22675\",\"put\":\"/api/v1/tasks/22675\",\"authenticated\":\"http://local.taskrabbit.com/go/a89862d84f6a3b8b3175c46bc824ba3c4086519395730898237d56ef90ad672e540e62370c6a87b6c6ec2f601c10e2486ba7\"},\"runners\":{\"items\":[]},\"state_label\":\"posted\",\"assign_by_time\":1332082800,\"state\":\"opened\"}],\"links\":{\"get\":\"/api/v1/users/49720/tasks\",\"last\":\"/api/v1/users/49720/tasks?page=1\",\"first\":\"/api/v1/users/49720/tasks?page=1\"}},\"short_name\":\"Bob\",\"full_name\":\"Bob Sponge\",\"last_name\":\"Sponge\",\"links\":{\"get\":\"/api/v1/users/49720\",\"avatar_url\":\"http://local.taskrabbit.com/images/default_avatars/poster_thumb.png\"},\"display_name\":\"Bob S.\",\"locations\":{\"items\":[{\"name\":\"Home\",\"city\":\"San Francisco\",\"approximate_radius\":0,\"address\":\"432 example\",\"zip\":\"94123\",\"partial\":\"example, San Francisco, Ca 94123\",\"id\":37439,\"lng\":2.108266,\"complete\":\"432 example, San Francisco, Ca 94123\",\"lat\":41.5512199,\"state\":\"Ca\"}],\"links\":{\"get\":\"/api/v1/users/49720/locations\"}},\"email\":\"bobsponge@example.com\",\"first_name\":\"Bob\",\"counts\":{\"posted_tasks\":30,\"active_tasks\":3,\"ongoing_tasks\":3}}"
32
+ http_version: "1.1"
33
+ - !ruby/struct:VCR::HTTPInteraction
34
+ request: !ruby/struct:VCR::Request
35
+ method: :get
36
+ uri: http://localhost:3000/api/v1/users/49720/tasks?
37
+ body:
38
+ headers:
39
+ x-client-application:
40
+ - euqmQpzV04GmN1dJTY639PdI7eiSjCjI3lKTkPWn
41
+ authorization:
42
+ - OAuth RhyRtRg1bRNyqmdozkY6JJJ3eGDpoRGTm9AXUudp
43
+ response: !ruby/struct:VCR::Response
44
+ status: !ruby/struct:VCR::ResponseStatus
45
+ code: 200
46
+ message: OK
47
+ headers:
48
+ etag:
49
+ - "\"db8123183fb4c9fbd9a9ccc993954b78\""
50
+ content-type:
51
+ - application/json; charset=utf-8
52
+ x-runtime:
53
+ - "3288"
54
+ server:
55
+ - WEBrick/1.3.1 (Ruby/1.8.7/2011-02-18)
56
+ date:
57
+ - Sat, 17 Mar 2012 23:12:24 GMT
58
+ content-length:
59
+ - "2163"
60
+ cache-control:
61
+ - private, max-age=0, must-revalidate
62
+ body: "{\"items\":[{\"city\":{\"name\":\"New York City\",\"lng\":-74.005973,\"id\":4,\"links\":{\"get\":\"/api/v1/cities/4\"},\"lat\":40.714353},\"name\":\"My First Task\",\"charge_price\":20,\"named_price\":20,\"private_runner\":false,\"complete_by_time\":1332093600,\"cost_in_cents\":0,\"state_changed_at\":1332025380,\"id\":22673,\"runners\":{\"items\":[]},\"links\":{\"html\":\"http://local.taskrabbit.com/tasks/my-first-task--47\",\"get\":\"/api/v1/tasks/22673\",\"delete\":\"/api/v1/tasks/22673\",\"put\":\"/api/v1/tasks/22673\",\"authenticated\":\"http://local.taskrabbit.com/go/2f249e87a04016d741f163fe991468737e367c8e334eb5d5a53a63d741ce0019ba1a9c33366a76cadc06bdcb9259c5549a44\"},\"state_label\":\"posted\",\"assign_by_time\":1332082800,\"state\":\"opened\"},{\"city\":{\"name\":\"New York City\",\"lng\":-74.005973,\"id\":4,\"links\":{\"get\":\"/api/v1/cities/4\"},\"lat\":40.714353},\"name\":\"New Name\",\"charge_price\":20,\"named_price\":20,\"private_runner\":false,\"complete_by_time\":1332093600,\"cost_in_cents\":0,\"state_changed_at\":1332025387,\"id\":22674,\"runners\":{\"items\":[]},\"links\":{\"html\":\"http://local.taskrabbit.com/tasks/new-name--3\",\"get\":\"/api/v1/tasks/22674\",\"delete\":\"/api/v1/tasks/22674\",\"put\":\"/api/v1/tasks/22674\",\"authenticated\":\"http://local.taskrabbit.com/go/459b5e05e7a6542891148717ed9cdd4a25fb5d5f71f094c098a93beb25ba26303c4ea5e2c8e01da3743703abbe1da5b46980\"},\"state_label\":\"posted\",\"assign_by_time\":1332082800,\"state\":\"opened\"},{\"city\":{\"name\":\"New York City\",\"lng\":-74.005973,\"id\":4,\"links\":{\"get\":\"/api/v1/cities/4\"},\"lat\":40.714353},\"name\":\"My First Task\",\"charge_price\":20,\"named_price\":20,\"private_runner\":false,\"complete_by_time\":1332093600,\"cost_in_cents\":0,\"state_changed_at\":1332025394,\"id\":22675,\"runners\":{\"items\":[]},\"links\":{\"html\":\"http://local.taskrabbit.com/tasks/my-first-task--49\",\"get\":\"/api/v1/tasks/22675\",\"delete\":\"/api/v1/tasks/22675\",\"put\":\"/api/v1/tasks/22675\",\"authenticated\":\"http://local.taskrabbit.com/go/a89862d84f6a3b8b3175c46bc824ba3c4086519395730898237d56ef90ad672e540e62370c6a87b6c6ec2f601c10e2486ba7\"},\"state_label\":\"posted\",\"assign_by_time\":1332082800,\"state\":\"opened\"}],\"links\":{\"get\":\"/api/v1/users/49720/tasks\",\"last\":\"/api/v1/users/49720/tasks?page=1\",\"first\":\"/api/v1/users/49720/tasks?page=1\"}}"
63
+ http_version: "1.1"