shared_workforce 0.2.14 → 0.3.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.
data/README.markdown CHANGED
@@ -81,6 +81,14 @@ end
81
81
  ```
82
82
  _**Note:** the task definition includes a `setup` method which is called automatically whenever the task is initialized. In the example, the task's `image_url` (the image shown to the worker) is set from the photo model's url attribute. Any of the task's attributes can be set this way._
83
83
 
84
+ Class level attributes are a handy way of defining data that doesn't change between each task.
85
+ Attributes set on the instance will always override attributes set at the class level.
86
+
87
+ In most cases, you'll want to explicitly set default task values at the class level
88
+ (like `title` and `instruction`). Setting `text`
89
+ and `image_url` values (i.e. the content in question) will usually be done in
90
+ the `setup` method.</p>
91
+
84
92
  Once you have created a task definition, you can request real human responses for a model instance by calling its `create` method. This can be done in an `after_create` callback in one of your Active Record models. This will be covered in more detail in the next section.
85
93
 
86
94
  ### Step 4 - request tasks
@@ -102,6 +110,16 @@ _**Note:** In the example, the photo model instance (self) is used an argument t
102
110
 
103
111
  When the response(s) from the human workers are collected, the method specified in the `on_success` attribute in your task definition will be called. Typically this will take about 15 minutes. You can check the [Shared Workforce web site](http://www.sharedworkforce.com) for an up to date status on the current response time.
104
112
 
113
+ ### Step 5 - collect responses
114
+
115
+ A rake task is provided for collecting the responses *during development*.
116
+
117
+ ```
118
+ $ rake sw:collect
119
+ ```
120
+
121
+ There is no requirement to run the rake task in production. The webhook will be used to deliver the task responses.
122
+
105
123
  ### Unit testing
106
124
 
107
125
  You can test your task definition by calling its methods directly.
@@ -31,7 +31,7 @@ module SharedWorkforce
31
31
  end
32
32
 
33
33
  def logger
34
- @logger ||= (rails_logger || default_logger)
34
+ @logger ||= default_logger
35
35
  end
36
36
 
37
37
  def valid?
@@ -43,7 +43,7 @@ module SharedWorkforce
43
43
  def default_request_class
44
44
  if defined?(Rails)
45
45
  if Rails.env.development?
46
- TaskRequest::HttpWithPoller
46
+ TaskRequest::HttpWithoutCallbacks
47
47
  elsif Rails.env.test?
48
48
  TaskRequest::BlackHole
49
49
  else
@@ -60,10 +60,14 @@ module SharedWorkforce
60
60
  end
61
61
 
62
62
  def default_logger
63
- require 'logger'
64
- l = ::Logger.new($stdout)
65
- l.level = ::Logger::INFO
66
- l
63
+ if !rails_logger || (defined?(Rails) && Rails.env.development?)
64
+ require 'logger'
65
+ l = ::Logger.new($stdout)
66
+ l.level = ::Logger::INFO
67
+ l
68
+ else
69
+ rails_logger
70
+ end
67
71
  end
68
72
  end
69
73
  end
@@ -7,12 +7,15 @@ if defined?(ActionController::Metal)
7
7
  if SharedWorkforce.configuration.valid?
8
8
  # Stop log buffering when using Foreman in development
9
9
  $stdout.sync = true
10
- SharedWorkforce::ResponsePoller.start
11
10
  else
12
11
  puts 'Shared Workforce: API key not configured.'
13
12
  end
14
13
  end
15
14
  end
16
15
  end
16
+
17
+ rake_tasks do
18
+ load "shared_workforce/tasks/collect.rake" if Rails.env.development?
19
+ end
17
20
  end
18
21
  end
@@ -0,0 +1,50 @@
1
+ module SharedWorkforce
2
+ class ResponseCollector
3
+
4
+ attr_accessor :interval
5
+
6
+ def self.start(interval=nil)
7
+ new.start(interval)
8
+ end
9
+
10
+ def start(interval)
11
+ @interval = interval
12
+ process_tasks completed_tasks
13
+ sleep interval if interval
14
+ end
15
+
16
+ private
17
+
18
+ def process_tasks(tasks)
19
+ if tasks.any?
20
+ tasks.each do |task|
21
+ if task['state'] == "completed"
22
+ SharedWorkforce.logger.info "=> #{task['title']} (#{task['id']}) complete. Loading responses."
23
+ responses = collect_responses(task['id'])
24
+
25
+ SharedWorkforce::TaskResult.new(responses).process!
26
+ SharedWorkforce.logger.info "=> Done."
27
+ end
28
+ end
29
+ elsif !interval
30
+ SharedWorkforce.logger.info "=> No responses to collect."
31
+ end
32
+ end
33
+
34
+ def completed_tasks
35
+ JSON.parse(RestClient.get("#{SharedWorkforce.configuration.http_end_point}/tasks/unreturned", {
36
+ 'X-API-Key'=>SharedWorkforce.configuration.api_key,
37
+ :content_type => :json,
38
+ :accept => :json
39
+ }))
40
+ end
41
+
42
+ def collect_responses(id)
43
+ JSON.parse(RestClient.get("#{SharedWorkforce.configuration.http_end_point}/tasks/#{id}/responses/collect", {
44
+ 'X-API-Key'=>SharedWorkforce.configuration.api_key,
45
+ :content_type => :json,
46
+ :accept => :json
47
+ }))
48
+ end
49
+ end
50
+ end
@@ -90,6 +90,7 @@ module SharedWorkforce
90
90
  end
91
91
 
92
92
  def process_result(result)
93
+ SharedWorkforce.logger.info("Shared Workforce: processing responses for #{title}")
93
94
  initialize_attributes(result.callback_params)
94
95
  success!(result)
95
96
  complete!(result)
@@ -112,6 +113,7 @@ module SharedWorkforce
112
113
  end
113
114
 
114
115
  def request(options = {})
116
+ SharedWorkforce.logger.info("Shared Workforce: creating task #{title}")
115
117
  task_request = remote_request(self, options)
116
118
  task_request.create
117
119
  end
@@ -1,6 +1,6 @@
1
1
  require 'rest_client'
2
2
  module SharedWorkforce
3
- class TaskRequest::HttpWithPoller < TaskRequest::Http
3
+ class TaskRequest::HttpWithoutCallbacks < TaskRequest::Http
4
4
  # Disable callbacks during development
5
5
  def request_params
6
6
  [{:task=>@task.to_hash.merge(@params).merge(:callback_url=>callback_url, :callback_enabled=>false), :api_key=>api_key}.to_json, {:content_type => :json, :accept => :json}]
@@ -0,0 +1,19 @@
1
+ desc "Collects completed responses"
2
+ namespace :shared_workforce do
3
+ task :collect => :environment do
4
+ $stdout.sync = true
5
+ puts "=> Please note: expect a delay of about 30 seconds after a task is completed before seeing a response."
6
+ puts "=> This gives the worker a chance to change their answer."
7
+ puts "=> Connecting to Shared Workforce..."
8
+ SharedWorkforce::ResponseCollector.start
9
+ end
10
+ end
11
+
12
+ namespace :sw do
13
+ desc "Alias of shared_workforce:collect"
14
+ task :collect => "shared_workforce:collect"
15
+ end
16
+
17
+ namespace :sharedworkforce do
18
+ task :collect => "shared_workforce:collect"
19
+ end
@@ -1,4 +1,4 @@
1
1
  module SharedWorkforce
2
- VERSION = "0.2.14"
2
+ VERSION = "0.3.0"
3
3
 
4
4
  end
@@ -6,11 +6,11 @@ require 'shared_workforce/task'
6
6
  require 'shared_workforce/task_request/task_request'
7
7
  require 'shared_workforce/task_request/black_hole'
8
8
  require 'shared_workforce/task_request/http'
9
- require 'shared_workforce/task_request/http_with_poller'
9
+ require 'shared_workforce/task_request/http_without_callbacks'
10
10
  require 'shared_workforce/task_result'
11
11
  require 'shared_workforce/task_response'
12
12
  require 'shared_workforce/end_point'
13
- require 'shared_workforce/response_poller'
13
+ require 'shared_workforce/response_collector'
14
14
  require 'shared_workforce/frameworks/rails' if defined?(Rails)
15
15
  require 'active_support/inflector'
16
16
  require 'active_support/core_ext/hash/indifferent_access'
@@ -1,10 +1,10 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
- describe "TaskRequest::HttpWithPoller" do
3
+ describe "TaskRequest::HttpWithoutCallbacks" do
4
4
  describe "#create" do
5
5
  it "should disable callbacks" do
6
6
  task = ApprovePhotoTask.new
7
- task_request = SharedWorkforce::TaskRequest::HttpWithPoller.new(task,
7
+ task_request = SharedWorkforce::TaskRequest::HttpWithoutCallbacks.new(task,
8
8
  :image_url=>"http://www.google.com/logo.png",
9
9
  :image_crop_ratio=>1.7,
10
10
  :callback_params=>{:resource_id=>'1234'}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shared_workforce
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.14
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-20 00:00:00.000000000 Z
12
+ date: 2012-09-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
16
- requirement: &70318914187300 !ruby/object:Gem::Requirement
16
+ requirement: &70263277593000 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70318914187300
24
+ version_requirements: *70263277593000
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: json
27
- requirement: &70318914186880 !ruby/object:Gem::Requirement
27
+ requirement: &70263277592580 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70318914186880
35
+ version_requirements: *70263277592580
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: activesupport
38
- requirement: &70318914186460 !ruby/object:Gem::Requirement
38
+ requirement: &70263277608420 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70318914186460
46
+ version_requirements: *70263277608420
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
- requirement: &70318914185960 !ruby/object:Gem::Requirement
49
+ requirement: &70263277607380 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.2.9
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70318914185960
57
+ version_requirements: *70263277607380
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: webmock
60
- requirement: &70318914185540 !ruby/object:Gem::Requirement
60
+ requirement: &70263277606740 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70318914185540
68
+ version_requirements: *70263277606740
69
69
  description: Shared Workforce is a service and simple API for human intelligence tasks
70
70
  email:
71
71
  - sam@samoliver.com
@@ -84,14 +84,15 @@ files:
84
84
  - lib/shared_workforce/end_point.rb
85
85
  - lib/shared_workforce/exceptions.rb
86
86
  - lib/shared_workforce/frameworks/rails.rb
87
- - lib/shared_workforce/response_poller.rb
87
+ - lib/shared_workforce/response_collector.rb
88
88
  - lib/shared_workforce/task.rb
89
89
  - lib/shared_workforce/task_request/black_hole.rb
90
90
  - lib/shared_workforce/task_request/http.rb
91
- - lib/shared_workforce/task_request/http_with_poller.rb
91
+ - lib/shared_workforce/task_request/http_without_callbacks.rb
92
92
  - lib/shared_workforce/task_request/task_request.rb
93
93
  - lib/shared_workforce/task_response.rb
94
94
  - lib/shared_workforce/task_result.rb
95
+ - lib/shared_workforce/tasks/collect.rake
95
96
  - lib/shared_workforce/version.rb
96
97
  - shared_workforce.gemspec
97
98
  - spec/.rspec
@@ -103,7 +104,7 @@ files:
103
104
  - spec/support/configuration_helper.rb
104
105
  - spec/task_request/black_hole_spec.rb
105
106
  - spec/task_request/http_spec.rb
106
- - spec/task_request/http_with_poller_spec.rb
107
+ - spec/task_request/http_without_callbacks_spec.rb
107
108
  - spec/task_response_spec.rb
108
109
  - spec/task_result_spec.rb
109
110
  - spec/task_spec.rb
@@ -141,7 +142,7 @@ test_files:
141
142
  - spec/support/configuration_helper.rb
142
143
  - spec/task_request/black_hole_spec.rb
143
144
  - spec/task_request/http_spec.rb
144
- - spec/task_request/http_with_poller_spec.rb
145
+ - spec/task_request/http_without_callbacks_spec.rb
145
146
  - spec/task_response_spec.rb
146
147
  - spec/task_result_spec.rb
147
148
  - spec/task_spec.rb
@@ -1,52 +0,0 @@
1
- module SharedWorkforce
2
- class ResponsePoller
3
- # The response poller is intended for use during local development only. It
4
- # facilitates real world task responses without needing an open socket for the
5
- # web hooks.
6
-
7
- def self.start(interval=60)
8
- new.start(interval)
9
- end
10
-
11
- def start(interval)
12
- Thread.abort_on_exception = true
13
- Thread.new do
14
- SharedWorkforce.logger.info "SharedWorkforce: Checking every #{interval} seconds for new responses."
15
-
16
- while true
17
- SharedWorkforce.logger.info "SharedWorkforce: Checking for new task responses."
18
- process_tasks completed_tasks
19
- sleep interval
20
- end
21
- end
22
- end
23
-
24
- private
25
-
26
- def process_tasks(tasks)
27
- tasks.each do |task|
28
- if task['state'] == "completed"
29
- SharedWorkforce.logger.info "SharedWorkforce: Task complete. Getting responses."
30
- responses = collect_responses(task['id'])
31
- SharedWorkforce::TaskResult.new(responses).process!
32
- end
33
- end
34
- end
35
-
36
- def completed_tasks
37
- JSON.parse(RestClient.get("#{SharedWorkforce.configuration.http_end_point}/tasks/unreturned", {
38
- 'X-API-Key'=>SharedWorkforce.configuration.api_key,
39
- :content_type => :json,
40
- :accept => :json
41
- }))
42
- end
43
-
44
- def collect_responses(id)
45
- JSON.parse(RestClient.get("#{SharedWorkforce.configuration.http_end_point}/tasks/#{id}/responses/collect", {
46
- 'X-API-Key'=>SharedWorkforce.configuration.api_key,
47
- :content_type => :json,
48
- :accept => :json
49
- }))
50
- end
51
- end
52
- end