crowdflower 0.7.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README.md +408 -28
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/crowdflower.gemspec +3 -3
- data/lib/crowdflower/base.rb +17 -1
- data/lib/crowdflower/job.rb +2 -2
- data/lib/crowdflower/judgment.rb +0 -9
- data/lib/crowdflower/order.rb +5 -3
- data/lib/crowdflower/worker.rb +17 -26
- data/test/integration_tests.rb +19 -19
- metadata +3 -3
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,41 +1,421 @@
|
|
1
|
-
|
1
|
+
CrowdFlower API Gem
|
2
|
+
========
|
3
|
+
Currently this is a toolkit for interacting with the CrowdFlower REST API. It may potentially become a complete Ruby gem for accessing and editing [CrowdFlower](http://crowdflower.com) jobs.
|
2
4
|
|
3
|
-
|
5
|
+
## Table of Contents
|
4
6
|
|
5
|
-
|
7
|
+
1. [Getting Started](#getting-started)
|
8
|
+
2. [Usage and Examples](#usage-and-examples)
|
9
|
+
3. [Helpful Documentation Links](#helpful-documentation-links)
|
10
|
+
4. [Contribute](#contribute)
|
11
|
+
5. [Team](#team)
|
12
|
+
6. [License](#license)
|
6
13
|
|
7
|
-
|
8
|
-
-------------
|
14
|
+
## Getting Started
|
9
15
|
|
10
|
-
|
11
|
-
|
12
|
-
CrowdFlower.connect!( 'CrowdFlower.yml' )
|
13
|
-
|
14
|
-
Upload a CSV file for a job:
|
16
|
+
#####Add this line to your application's Gemfile:
|
15
17
|
|
16
|
-
|
18
|
+
$ gem 'crowdflower'
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
new_job = job.copy( :all_units => true )
|
21
|
-
|
22
|
-
Check the status of a job:
|
20
|
+
#####Then execute:
|
23
21
|
|
24
|
-
|
22
|
+
$ bundle install
|
25
23
|
|
24
|
+
#####Or install it yourself as:
|
26
25
|
|
26
|
+
$ gem install crowdflower
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
#####And require the gem in your ruby file as:
|
29
|
+
|
30
|
+
require 'crowdflower'
|
30
31
|
|
31
|
-
|
32
|
-
2. Create a topic branch - `git checkout -b my_branch`
|
33
|
-
3. Make your feature addition or bug fix and add tests for it.
|
34
|
-
4. Commit, but do not mess with the rakefile, version, or history.
|
35
|
-
5. Push to your branch - `git push origin my_branch`
|
36
|
-
6. Create an Issue with a link to your branch
|
32
|
+
This gem makes use of [CrowdFlower's API](http://success.crowdflower.com/customer/portal/articles/1288323-api-documentation). To find your API key, click on your name in the upper right hand corner and select "Account" from the drop down. To create an account click [here](https://id.crowdflower.com/registrations/new?redirect_url=https%3A%2F%2Fcrowdflower.com%2Fjobs&app=make&__hssc=14529640.6.1397164984954&__hstc=14529640.8f31cd290788fdc43f4da6707700cde6.1396463439689.1397160539873.1397164984954.16&hsCtaTracking=c85b8d58-818e-4f19-a27e-83e8f55da890%7C583ca9bc-a025-43b9-806a-b329df96a8c6).
|
37
33
|
|
38
|
-
|
39
|
-
---------
|
34
|
+
#####Specify your api key directly in your code or store it in a yaml file:
|
40
35
|
|
41
|
-
|
36
|
+
```ruby
|
37
|
+
API_KEY = "YOUR_API_KEY"
|
38
|
+
|
39
|
+
CrowdFlower.connect!( 'CrowdFlower.yaml' )
|
40
|
+
```
|
41
|
+
|
42
|
+
## Usage and Examples
|
43
|
+
#####[Example Job](https://api.crowdflower.com/v1/jobs/418404/) - referenced throught the following examples (must be signed in to view).
|
44
|
+
|
45
|
+
### Access Job Info
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'crowdflower'
|
49
|
+
|
50
|
+
API_KEY = "YOUR_API_KEY"
|
51
|
+
DOMAIN_BASE = "https://api.crowdflower.com"
|
52
|
+
|
53
|
+
CrowdFlower::Job.connect! API_KEY, DOMAIN_BASE
|
54
|
+
|
55
|
+
job = CrowdFlower::Job.new(job_id)
|
56
|
+
job = CrowdFlower::Job.new(418404)
|
57
|
+
```
|
58
|
+
### Create Blank Job
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
require 'crowdflower'
|
62
|
+
|
63
|
+
API_KEY = "YOUR_API_KEY"
|
64
|
+
DOMAIN_BASE = "https://api.crowdflower.com"
|
65
|
+
|
66
|
+
CrowdFlower::Job.connect! API_KEY, DOMAIN_BASE
|
67
|
+
|
68
|
+
title = "Crowdshop for Shoes!"
|
69
|
+
job = CrowdFlower::Job.create(title)
|
70
|
+
```
|
71
|
+
|
72
|
+
### Copy Existing Job
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
require 'crowdflower'
|
76
|
+
|
77
|
+
API_KEY = "YOUR_API_KEY"
|
78
|
+
DOMAIN_BASE = "https://api.crowdflower.com"
|
79
|
+
JOB_ID = 418404
|
80
|
+
|
81
|
+
CrowdFlower::Job.connect! API_KEY, DOMAIN_BASE
|
82
|
+
|
83
|
+
job_one = CrowdFlower::Job.new(job_id)
|
84
|
+
job_two = job_one.copy
|
85
|
+
```
|
86
|
+
|
87
|
+
### Available Features (Methods)
|
88
|
+
|
89
|
+
#####GET - https://crowdflower.com/jobs/418404.json
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
job.get["css"]
|
93
|
+
job.get["auto_order"]
|
94
|
+
job.get["units_remain_finalized"]
|
95
|
+
job.get["secret"]
|
96
|
+
job.get["support_email"]
|
97
|
+
job.get["golds_count"]
|
98
|
+
job.get["units_count"]
|
99
|
+
job.get["included_countries"]
|
100
|
+
job.get["desired_requirements"]
|
101
|
+
job.get["max_judgments_per_unit"]
|
102
|
+
job.get["instructions"]
|
103
|
+
job.get["auto_order_timeout"]
|
104
|
+
job.get["public_data"]
|
105
|
+
job.get["project_number"]
|
106
|
+
job.get["problem"]
|
107
|
+
job.get["created_at"]
|
108
|
+
job.get["send_judgments_webhook"]
|
109
|
+
job.get["expected_judgments_per_unit"]
|
110
|
+
job.get["design_verified"]
|
111
|
+
job.get["worker_ui_remix"]
|
112
|
+
job.get["fields"]
|
113
|
+
job.get["completed_at"]
|
114
|
+
job.get["auto_order_threshold"]
|
115
|
+
job.get["min_unit_confidence"]
|
116
|
+
job.get["minimum_account_age_seconds"]
|
117
|
+
job.get["units_per_assignment"]
|
118
|
+
job.get["execution_mode"]
|
119
|
+
job.get["max_judgments_per_worker"]
|
120
|
+
job.get["gold"]
|
121
|
+
job.get["require_worker_login"]
|
122
|
+
job.get["pages_per_assignment"]
|
123
|
+
job.get["title"]
|
124
|
+
job.get["completed"]
|
125
|
+
job.get["order_approved"]
|
126
|
+
job.get["minimum_requirements"]
|
127
|
+
job.get["max_judgments_per_ip"]
|
128
|
+
job.get["confidence_fields"]
|
129
|
+
job.get["gold_per_assignment"]
|
130
|
+
job.get["alias"]
|
131
|
+
job.get["id"]
|
132
|
+
job.get["judgments_count"]
|
133
|
+
job.get["js"]
|
134
|
+
job.get["cml"]
|
135
|
+
job.get["excluded_countries"]
|
136
|
+
job.get["updated_at"]
|
137
|
+
job.get["language"]
|
138
|
+
job.get["state"]
|
139
|
+
job.get["variable_judgments_mode"]
|
140
|
+
job.get["custom_key"]
|
141
|
+
job.get["options"]
|
142
|
+
```
|
143
|
+
|
144
|
+
#####UPLOAD (data to create units)
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
job.upload(filename, type, opts)
|
148
|
+
job.upload("crowdshopping.csv", "text/csv")
|
149
|
+
```
|
150
|
+
|
151
|
+
#####CHANNELS - http://api.crowdflower.com/v1/jobs/418404/channels
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
job.channels
|
155
|
+
job.enable_channels(channels)
|
156
|
+
job.enable_channels("cf_internal")
|
157
|
+
```
|
158
|
+
|
159
|
+
#####TAGS - https://api.crowdflower.com/jobs/418404/tags
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
tags = "shoes", "shopping", "fashion"
|
163
|
+
job.add_tags(tags)
|
164
|
+
job.update_tags("fun", "glitter", "crowdshop")
|
165
|
+
job.remove_tags("crowdshop")
|
166
|
+
```
|
167
|
+
|
168
|
+
#####UNITS: http://api.crowdflower.com/v1/jobs/418404/units
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
unit = CrowdFlower::Unit.new(job)
|
172
|
+
```
|
173
|
+
|
174
|
+
#####UNIT.ALL: View all units or count all units in a job; same result as job.units.
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
unit.all
|
178
|
+
unit.all.count
|
179
|
+
```
|
180
|
+
|
181
|
+
#####UNIT.GET: Get info about a unit by passing in the unit's ID.units.
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
unit.get(unit_id)
|
185
|
+
```
|
186
|
+
#####UNIT.PING: Returns the status of all units in a job.
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
unit.ping
|
190
|
+
```
|
191
|
+
|
192
|
+
#####UNIT.JUDGMENTS: View all judgments for a specific unit by passing in the unit_id.
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
unit.judgments(unit_id)
|
196
|
+
unit.judgments(444154130)
|
197
|
+
```
|
198
|
+
|
199
|
+
#####UNIT.CREATE: Create a new unit.
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
unit.create("glitter_color"=>"blue")
|
203
|
+
unit.create("glitter_color"=>"blue", gold: true)
|
204
|
+
```
|
205
|
+
|
206
|
+
#####UNIT.COPY: Copy an existing unit.
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
unit.copy(unit_id, job_id, data = {})
|
210
|
+
unit.copy(444154130, 418404, "glitter_color"=>"blue")
|
211
|
+
```
|
212
|
+
|
213
|
+
#####UNIT.SPLIT: In cases where multiple values are stored in the cells of the same column, you can use the Split Column function to parse the data into two or more columns by specifying a delimiter (most typically a newline character).
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
unit.split(on, with = " ")
|
217
|
+
```
|
218
|
+
|
219
|
+
#####UNIT.UPDATE: Update the value of a unit's key.
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
unit.update(unit_id, params)
|
223
|
+
unit.update(444154130, "glitter_color"=>"green")
|
224
|
+
```
|
225
|
+
|
226
|
+
#####UNIT.MAKE_GOLD: Turn an existing unit into a test question (gold) unit.
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
unit.make_gold(unit_id)
|
230
|
+
```
|
231
|
+
|
232
|
+
#####UNIT.CANCEL: Cancel a unit.
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
unit.cancel(unit_id)
|
236
|
+
```
|
237
|
+
|
238
|
+
#####UNIT.DELETE: Delete a unit.
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
unit.delete(unit_id)
|
242
|
+
```
|
243
|
+
|
244
|
+
#####UNIT.REQUEST_MORE_JUDGMENTS: Get more answers (judgments) for a specific unit by using this method with the unit's id and the amount of requested judgments passed as params.
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
unit.request_more_judgments(unit_id, nb_judgments = 1)
|
248
|
+
```
|
249
|
+
|
250
|
+
#####ORDER: Set up an order using your job's id.
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
order = CrowdFlower::Order.new(job)
|
254
|
+
```
|
255
|
+
|
256
|
+
#####ORDER.DEBIT: When a job has data (units) and properly working cml, it is ready to launch. The launch tab on the job dashboard is the same as calling order.debit.
|
257
|
+
|
258
|
+
```ruby
|
259
|
+
# defaults to on_demand channels
|
260
|
+
order.debit(units_count, channels = ["on_demand"])
|
261
|
+
|
262
|
+
# pass in specific channel name to launch job w/ that channel
|
263
|
+
order.debit(6, "cf_internal")
|
264
|
+
```
|
265
|
+
|
266
|
+
#####PAUSE: Only can be called on running jobs.
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
job.pause
|
270
|
+
```
|
271
|
+
|
272
|
+
#####RESUME: Only can be called on paused or completed jobs.
|
273
|
+
|
274
|
+
```ruby
|
275
|
+
job.resume
|
276
|
+
```
|
277
|
+
|
278
|
+
#####CANCEL: Only can be called on paused jobs.
|
279
|
+
|
280
|
+
```ruby
|
281
|
+
job.cancel
|
282
|
+
```
|
283
|
+
|
284
|
+
#####UPDATE: Update any of the JSON attributes that get can access. Scroll up to GET to see the full list of accessible attributes.
|
285
|
+
|
286
|
+
```ruby
|
287
|
+
job.update
|
288
|
+
job.update("project_number"=>"PN123")
|
289
|
+
```
|
290
|
+
|
291
|
+
#####DELETE: Delete the entire job.
|
292
|
+
|
293
|
+
```ruby
|
294
|
+
job.delete
|
295
|
+
```
|
296
|
+
|
297
|
+
#####WORKERS: http://api.crowdflower.com/v1/jobs/418404/workers
|
298
|
+
|
299
|
+
```ruby
|
300
|
+
worker = CrowdFlower::Worker.new(job)
|
301
|
+
```
|
302
|
+
|
303
|
+
#####WORKER.BONUS: Award a bonus in cents, 200 for $2.00 and (optionally) add a message
|
304
|
+
|
305
|
+
```ruby
|
306
|
+
worker.bonus(worker_id, amount, reason=nil)
|
307
|
+
worker.bonus(23542619, 200, "You shoe shop like a pro! Thanks for the awesome answers!")
|
308
|
+
```
|
309
|
+
|
310
|
+
#####WORKER.REJECT: Stops contributors from completing tasks, and removes the contributors judgments from a job. Try to only use when a job is running, otherwise the completed job will lose judgments and be unable to collect replacement ones.
|
311
|
+
|
312
|
+
```ruby
|
313
|
+
worker.reject(worker_id)
|
314
|
+
worker.reject(14952322)
|
315
|
+
```
|
316
|
+
|
317
|
+
#####WORKER.NOTIFY: Sends a notification to a specific contributor. The contributor will see the message under their notifications.
|
318
|
+
|
319
|
+
```ruby
|
320
|
+
worker.notify(worker_id, subject, message)
|
321
|
+
worker.notify(23542619, "you earned a bonus!", "good job!")
|
322
|
+
```
|
323
|
+
|
324
|
+
#####WORKER.FLAG: Stops contributors from completing tasks. Their judgments remain in their current state of tainted or non-tainted and will not be thrown away.
|
325
|
+
|
326
|
+
```ruby
|
327
|
+
worker.flag(worker_id, reason=nil)
|
328
|
+
worker.flag(14952322, "testing")
|
329
|
+
```
|
330
|
+
|
331
|
+
#####WORKER.DEFLAG: Allows a flagged contributor to continue completing tasks.
|
332
|
+
```ruby
|
333
|
+
worker.deflag(worker_id)
|
334
|
+
worker.deflag(14952322)
|
335
|
+
```
|
336
|
+
|
337
|
+
#####JUDGMENTS - http://api.crowdflower.com/v1/jobs/418404/units/judgments
|
338
|
+
|
339
|
+
```ruby
|
340
|
+
judgment = CrowdFlower::Judgment.new(job)
|
341
|
+
judgment.all
|
342
|
+
judgment.get(judgment_id)
|
343
|
+
judgment.get(1239592918)
|
344
|
+
|
345
|
+
# Return every judgment for the given unit
|
346
|
+
job.units.judgments(unit_id_number)
|
347
|
+
job.units.judgments(444154130)
|
348
|
+
```
|
349
|
+
|
350
|
+
#####LEGEND: Returns all of the cml in a job; shows all questions and available answers, see example: http://api.crowdflower.com/v1/jobs/418404/legend.
|
351
|
+
|
352
|
+
```ruby
|
353
|
+
job.legend
|
354
|
+
```
|
355
|
+
|
356
|
+
#####STATUS: parsed JSON response or access attributes like GET
|
357
|
+
|
358
|
+
```ruby
|
359
|
+
job.status
|
360
|
+
job.status["golden_units"]
|
361
|
+
job.status["all_judgments"]
|
362
|
+
job.status["tainted_judgments"]
|
363
|
+
job.status["completed_units_estimate"]
|
364
|
+
job.status["needed_judgments"]
|
365
|
+
job.status["all_units"]
|
366
|
+
job.status["completed_non_gold_estimate"]
|
367
|
+
job.status["completed_gold_estimate"]
|
368
|
+
job.status["ordered_units"]
|
369
|
+
```
|
370
|
+
|
371
|
+
#####DOWNLOAD_CSV: Downloads a CSV of the job with results, sometimes as csv and sometimes as a zip containing the CSV.
|
372
|
+
|
373
|
+
```ruby
|
374
|
+
job.download_csv(type, filename, opts)
|
375
|
+
job.download_csv(full, nil, force:true)
|
376
|
+
```
|
377
|
+
|
378
|
+
## Helpful Documentation Links
|
379
|
+
|
380
|
+
* [Job Settings](http://success.crowdflower.com/customer/portal/articles/1373615-contributors---behavior-settings)
|
381
|
+
* [Data Management](http://success.crowdflower.com/customer/portal/articles/1288308-data)
|
382
|
+
* [Judgments](http://success.crowdflower.com/customer/portal/articles/1366723-job-settings---judgments)
|
383
|
+
* [Workers](http://success.crowdflower.com/customer/portal/articles/1288319-contributors---active-contributors)
|
384
|
+
|
385
|
+
## Contribute
|
386
|
+
|
387
|
+
1. Fork the repo: https://github.com/dolores/ruby-crowdflower.git
|
388
|
+
2. Create your topic branch (`git checkout -b my_branch`)
|
389
|
+
3. Make changes and add tests for those changes
|
390
|
+
3. Commit your changes, making sure not to change the rakefile, version or history (`git commit -am 'Adds cool, new README'`)
|
391
|
+
4. Push to your branch (`git push origin my_branch`)
|
392
|
+
5. Create an issue with a link to your branch for the pull request
|
393
|
+
|
394
|
+
## Team
|
395
|
+
|
396
|
+
Check out the [CrowdFlower Team](http://www.crowdflower.com/team)!
|
397
|
+
|
398
|
+
## License
|
399
|
+
|
400
|
+
Copyright (c) 2014 CrowdFlower
|
401
|
+
|
402
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
403
|
+
a copy of this software and associated documentation files (the
|
404
|
+
"Software"), to deal in the Software without restriction, including
|
405
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
406
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
407
|
+
permit persons to whom the Software is furnished to do so, subject to
|
408
|
+
the following conditions:
|
409
|
+
|
410
|
+
The above copyright notice and this permission notice shall be
|
411
|
+
included in all copies or substantial portions of the Software.
|
412
|
+
|
413
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
414
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
415
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
416
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
417
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
418
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
419
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
420
|
+
|
421
|
+
Please review our [Terms and Conditions](http://www.crowdflower.com/legal) page for detailed api usage and licensing information.
|
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ A toolkit for interacting with CrowdFlower via the REST API.
|
|
12
12
|
This is alpha software. Have fun!
|
13
13
|
|
14
14
|
EOF
|
15
|
-
gem.email = "brian@
|
15
|
+
gem.email = "brian@crowdflower.com"
|
16
16
|
gem.homepage = "http://github.com/dolores/ruby-crowdflower"
|
17
17
|
gem.authors = ["Brian P O'Rourke", "Chris Van Pelt"]
|
18
18
|
gem.add_dependency 'httparty', '>= 0.7.4'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.11.0
|
data/crowdflower.gemspec
CHANGED
@@ -5,13 +5,13 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "crowdflower"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.11.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Brian P O'Rourke", "Chris Van Pelt"]
|
12
|
-
s.date = "2014-
|
12
|
+
s.date = "2014-05-02"
|
13
13
|
s.description = "A toolkit for interacting with CrowdFlower via the REST API.\n\nThis is alpha software. Have fun!\n\n"
|
14
|
-
s.email = "brian@
|
14
|
+
s.email = "brian@crowdflower.com"
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
17
|
"README.md"
|
data/lib/crowdflower/base.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
module CrowdFlower
|
2
2
|
@@key = nil
|
3
3
|
@@domain = nil
|
4
|
+
@@request_hook = Proc.new do |*, &block|
|
5
|
+
block.call
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.request_hook=(hook)
|
9
|
+
@@request_hook = hook
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.request_hook
|
13
|
+
@@request_hook
|
14
|
+
end
|
4
15
|
|
5
16
|
class UsageError < StandardError ; end
|
6
17
|
|
@@ -59,7 +70,10 @@ module CrowdFlower
|
|
59
70
|
options ||= {}
|
60
71
|
options[:query] = (default_params.merge(options[:query] || {}))
|
61
72
|
options[:headers] = (self.class.default_options[:headers].merge(options[:headers] || {}))
|
62
|
-
|
73
|
+
|
74
|
+
CrowdFlower.request_hook.call(method_id, path, options) do
|
75
|
+
self.class.send(method_id, url(path), options)
|
76
|
+
end
|
63
77
|
else
|
64
78
|
super
|
65
79
|
end
|
@@ -185,3 +199,5 @@ module CrowdFlower
|
|
185
199
|
end
|
186
200
|
|
187
201
|
end
|
202
|
+
|
203
|
+
|
data/lib/crowdflower/job.rb
CHANGED
@@ -83,8 +83,8 @@ module CrowdFlower
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def download_csv(type = :full, filename = nil)
|
86
|
-
filename ||= "#{type.to_s[0].chr}#{@id}.
|
87
|
-
res = connection.get("#{resource_uri}/#{@id}.csv", {:format =>
|
86
|
+
filename ||= "#{type.to_s[0].chr}#{@id}.zip"
|
87
|
+
res = connection.get("#{resource_uri}/#{@id}.csv", {:format => "zip", :query => {:type => type}})
|
88
88
|
self.class.verify_response res
|
89
89
|
puts "Status... #{res.code.inspect}"
|
90
90
|
if res.code == 202
|
data/lib/crowdflower/judgment.rb
CHANGED
@@ -21,14 +21,5 @@ module CrowdFlower
|
|
21
21
|
def get(id)
|
22
22
|
connection.get("#{resource_uri}/#{id}")
|
23
23
|
end
|
24
|
-
|
25
|
-
# Reject an individual Judgment.
|
26
|
-
#
|
27
|
-
# *Admin-only && MTurk-only*
|
28
|
-
#
|
29
|
-
# @param [String,Integer] id The CrowdFlower id for the judgment to reject.
|
30
|
-
def reject( id, reedo = false, do_amt_reject = false )
|
31
|
-
connection.put( "#{resource_uri}/#{id}/reject", :headers => { "Content-Length" => "0" }, :body => { :redo => reedo ? "true" : "false", :do_amt_reject => do_amt_reject ? "true" : "false" } )
|
32
|
-
end
|
33
24
|
end
|
34
25
|
end
|
data/lib/crowdflower/order.rb
CHANGED
@@ -12,8 +12,10 @@ module CrowdFlower
|
|
12
12
|
"/jobs/#{@job.id}/orders.json"
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
# defaults to on_demand; pass in diff channel name to launch job with that channel
|
16
|
+
# use job.enable_channels("channel_name") if you to keep on_demand and add another channel
|
17
|
+
def debit(units_count = 1, channels = ["on_demand"])
|
18
|
+
connection.post(resource_uri, {:body => {:debit => {:units_count => units_count}, :channels => channels}})
|
17
19
|
end
|
18
20
|
end
|
19
|
-
end
|
21
|
+
end
|
data/lib/crowdflower/worker.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
module CrowdFlower
|
2
2
|
class Worker < Base
|
3
3
|
attr_reader :job
|
4
|
-
|
4
|
+
|
5
5
|
def initialize( job )
|
6
6
|
super job.connection
|
7
7
|
@job = job
|
8
8
|
connect
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def resource_uri
|
12
12
|
"/jobs/#{@job.id}/workers"
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def bonus( worker_id, amount, reason=nil )
|
16
16
|
params = {
|
17
17
|
:amount => amount,
|
@@ -19,37 +19,28 @@ module CrowdFlower
|
|
19
19
|
}
|
20
20
|
connection.post( "#{resource_uri}/#{worker_id}/bonus", :body => params )
|
21
21
|
end
|
22
|
-
|
23
|
-
def approve( worker_id )
|
24
|
-
connection.put( "#{resource_uri}/#{worker_id}/approve", :headers => { "Content-Length" => "0" } )
|
25
|
-
end
|
26
|
-
|
22
|
+
|
27
23
|
def reject( worker_id )
|
28
24
|
connection.put( "#{resource_uri}/#{worker_id}/reject", :headers => { "Content-Length" => "0" } )
|
29
25
|
end
|
30
|
-
|
31
|
-
def
|
32
|
-
connection.put( "#{resource_uri}/#{worker_id}/ban", :headers => { "Content-Length" => "0" } )
|
33
|
-
end
|
34
|
-
|
35
|
-
def deban( worker_id )
|
36
|
-
connection.put( "#{resource_uri}/#{worker_id}/deban", :headers => { "Content-Length" => "0" } )
|
37
|
-
end
|
38
|
-
|
39
|
-
def notify( worker_id, subject, message )
|
26
|
+
|
27
|
+
def notify( worker_id, message )
|
40
28
|
params = {
|
41
|
-
:subject => subject,
|
42
29
|
:message => message
|
43
30
|
}
|
44
|
-
connection.post( "#{resource_uri}/#{worker_id}/notify", :
|
31
|
+
connection.post( "#{resource_uri}/#{worker_id}/notify", :body => params )
|
45
32
|
end
|
46
|
-
|
47
|
-
def flag( worker_id, reason = nil )
|
48
|
-
|
33
|
+
|
34
|
+
def flag( worker_id, reason = nil, persist = false )
|
35
|
+
params = {
|
36
|
+
:reason => reason,
|
37
|
+
:persist => persist
|
38
|
+
}
|
39
|
+
connection.put( "#{resource_uri}/#{worker_id}/flag", :body => params, :headers => { "Content-Length" => "0" })
|
49
40
|
end
|
50
|
-
|
51
|
-
def deflag(
|
52
|
-
connection.put( "#{resource_uri}/#{worker_id}/deflag",
|
41
|
+
|
42
|
+
def deflag(worker_id, reason)
|
43
|
+
connection.put( "#{resource_uri}/#{worker_id}/deflag", :body => { :reason => reason }, :headers => { "Content-Length" => "0" })
|
53
44
|
end
|
54
45
|
end
|
55
46
|
end
|
data/test/integration_tests.rb
CHANGED
@@ -7,6 +7,7 @@ require 'json'
|
|
7
7
|
API_KEY = ENV["API_KEY"]
|
8
8
|
DOMAIN_BASE = ENV["DOMAIN_BASE"] || "https://api.localdev.crowdflower.com:8443"
|
9
9
|
|
10
|
+
CrowdFlower::Job.connect! API_KEY, DOMAIN_BASE
|
10
11
|
unless API_KEY && API_KEY.size > 3
|
11
12
|
puts <<EOF
|
12
13
|
|
@@ -57,7 +58,6 @@ def assert_exception_raised expected_exception_class
|
|
57
58
|
raise "exception #{expected_exception_class} has not been raised"
|
58
59
|
end
|
59
60
|
|
60
|
-
|
61
61
|
def say(msg)
|
62
62
|
$stdout.puts msg
|
63
63
|
end
|
@@ -115,14 +115,6 @@ assert job.units.ping['done'] == true
|
|
115
115
|
say "Getting the units for this job."
|
116
116
|
assert job.units.all.size == 8
|
117
117
|
|
118
|
-
say "Copying the existing job to a new one."
|
119
|
-
job2 = job.copy :all_units => true
|
120
|
-
|
121
|
-
say "-- Waiting for CrowdFlower to finish copying the job."
|
122
|
-
# You could also register a webhook to have CrowdFlower notify your
|
123
|
-
# server.
|
124
|
-
wait_until { job2.get["units_count"] == 8 }
|
125
|
-
|
126
118
|
say "Checking the status of the job."
|
127
119
|
assert job.status["tainted_judgments"] == 0
|
128
120
|
|
@@ -133,16 +125,6 @@ job.update({:title => 'testtt',
|
|
133
125
|
|
134
126
|
say "Registering a webhook."
|
135
127
|
job.update :webhook_uri => "http://localhost:8080/crowdflower"
|
136
|
-
|
137
|
-
say "Checking channels"
|
138
|
-
assert !job.channels['available_channels'].empty?
|
139
|
-
assert job.channels['enabled_channels'].empty?
|
140
|
-
job.enable_channels ['amt']
|
141
|
-
assert job.channels['enabled_channels'] == ['amt']
|
142
|
-
job.enable_channels ['mob']
|
143
|
-
assert job.channels['enabled_channels'].sort == ['amt', 'mob']
|
144
|
-
job.enable_channels ['mob']
|
145
|
-
assert job.channels['enabled_channels'].sort == ['amt', 'mob']
|
146
128
|
|
147
129
|
say "Tags"
|
148
130
|
assert job.tags.empty?
|
@@ -153,12 +135,30 @@ assert job.tags.map{|t| t["name"]} == ["testing_456"]
|
|
153
135
|
job.add_tags ["testing_789"]
|
154
136
|
assert job.tags.map{|t| t["name"]} == ["testing_456", "testing_789"]
|
155
137
|
|
138
|
+
say "Copying the existing job to a new one."
|
139
|
+
job2 = job.copy :all_units => true
|
140
|
+
|
141
|
+
say "-- Waiting for CrowdFlower to finish copying the job."
|
142
|
+
# You could also register a webhook to have CrowdFlower notify your
|
143
|
+
# server.
|
144
|
+
wait_until { job2.get["units_count"] == 8 }
|
145
|
+
|
156
146
|
say "Ordering the job."
|
157
147
|
order = CrowdFlower::Order.new(job)
|
158
148
|
unit_count = 8
|
159
149
|
order.debit(8)
|
160
150
|
wait_until { job.get["state"].casecmp('running') == 0}
|
161
151
|
|
152
|
+
say "Checking enabled_channels."
|
153
|
+
assert !job.channels["enabled_channels"].empty?
|
154
|
+
# To see exact list of enabled jobs:
|
155
|
+
# p job.channels["enabled_channels"]
|
156
|
+
|
157
|
+
say "Order job2 to check channels when specifying channel parameter."
|
158
|
+
order = CrowdFlower::Order.new(job2)
|
159
|
+
order.debit(8, "channel"=>"cf_internal")
|
160
|
+
assert job2.channels["enabled_channels"] == ["cf_internal"]
|
161
|
+
|
162
162
|
say "Canceling the unit."
|
163
163
|
unit_id = job.units.all.to_a[0][0]
|
164
164
|
unit = CrowdFlower::Unit.new(job)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crowdflower
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-
|
13
|
+
date: 2014-05-02 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: httparty
|
@@ -35,7 +35,7 @@ description: ! 'A toolkit for interacting with CrowdFlower via the REST API.
|
|
35
35
|
|
36
36
|
|
37
37
|
'
|
38
|
-
email: brian@
|
38
|
+
email: brian@crowdflower.com
|
39
39
|
executables: []
|
40
40
|
extensions: []
|
41
41
|
extra_rdoc_files:
|