taskrabbit 0.0.1

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 (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"