crowdflower 0.4.5 → 0.5.3

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/HISTORY.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.5.1 (2011-02-03)
2
+ * Added individual judgment rejection to API.
3
+
4
+ ## 0.5.0 (2011-02-01)
5
+ * Worker API added for managing workers (flagging, approving, etc.)
6
+
7
+ ## 0.4.6 (2010-12-17)
8
+ * Multiple API keys can be used simultaneously
9
+
1
10
  ## 0.4.0 (2010-03-25)
2
11
  * Allow key configuration from YAML
3
12
  * ruby-crowdflower is now just 'crowdflower'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.5
1
+ 0.5.2
data/crowdflower.gemspec CHANGED
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{crowdflower}
8
- s.version = "0.4.5"
8
+ s.version = "0.5.3"
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 = %q{2010-12-03}
12
+ s.date = %q{2011-02-10}
13
13
  s.description = %q{A toolkit for interacting with CrowdFlower via the REST API.
14
14
 
15
15
  This is alpha software. Have fun!
@@ -18,40 +18,38 @@ This is alpha software. Have fun!
18
18
  s.email = %q{brian@doloreslabs.com}
19
19
  s.extra_rdoc_files = [
20
20
  "LICENSE",
21
- "README.md"
21
+ "README.md"
22
22
  ]
23
23
  s.files = [
24
24
  ".document",
25
- ".gitignore",
26
- "CONTRIBUTORS",
27
- "HISTORY.md",
28
- "LICENSE",
29
- "README.md",
30
- "Rakefile",
31
- "VERSION",
32
- "bindev/cl_skel.rb",
33
- "bindev/crowdflower.rb",
34
- "crowdflower.gemspec",
35
- "lib/crowdflower.rb",
36
- "lib/crowdflower/base.rb",
37
- "lib/crowdflower/job.rb",
38
- "lib/crowdflower/judgment.rb",
39
- "lib/crowdflower/order.rb",
40
- "lib/crowdflower/unit.rb",
41
- "test/integration_tests.rb",
42
- "test/sample.csv"
25
+ "CONTRIBUTORS",
26
+ "HISTORY.md",
27
+ "LICENSE",
28
+ "README.md",
29
+ "Rakefile",
30
+ "VERSION",
31
+ "bindev/cl_skel.rb",
32
+ "bindev/crowdflower.rb",
33
+ "crowdflower.gemspec",
34
+ "lib/crowdflower.rb",
35
+ "lib/crowdflower/base.rb",
36
+ "lib/crowdflower/job.rb",
37
+ "lib/crowdflower/judgment.rb",
38
+ "lib/crowdflower/order.rb",
39
+ "lib/crowdflower/unit.rb",
40
+ "lib/crowdflower/worker.rb",
41
+ "test/integration_tests.rb",
42
+ "test/sample.csv"
43
43
  ]
44
44
  s.homepage = %q{http://github.com/dolores/ruby-crowdflower}
45
- s.rdoc_options = ["--charset=UTF-8"]
46
45
  s.require_paths = ["lib"]
47
- s.rubygems_version = %q{1.3.7}
46
+ s.rubygems_version = %q{1.5.0}
48
47
  s.summary = %q{a toolkit for the CrowdFlower API}
49
48
  s.test_files = [
50
49
  "test/integration_tests.rb"
51
50
  ]
52
51
 
53
52
  if s.respond_to? :specification_version then
54
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
53
  s.specification_version = 3
56
54
 
57
55
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
data/lib/crowdflower.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'httparty'
2
2
 
3
- %w{base job unit judgment order}.each do |file|
3
+ %w{base job unit judgment order worker}.each do |file|
4
4
  require File.dirname(__FILE__) +"/crowdflower/" + file
5
5
  end
@@ -13,42 +13,167 @@ module CrowdFlower
13
13
  end
14
14
  end
15
15
 
16
- module Defaults
17
- def self.included(base)
18
- base.send :include, HTTParty
19
- base.send :headers, "accept" => "application/json"
20
- base.send :format, :json
21
- base.extend ClassMethods
22
- end
23
-
24
- module ClassMethods
25
- def connect
26
- unless CrowdFlower.key
27
- raise UsageError, "Please establish a connection using 'CrowdFlower.connect!'"
28
- end
29
- self.base_uri CrowdFlower.domain
30
- self.default_params :key => CrowdFlower.key
16
+ # a convenience method for backward compatibility
17
+ def self.connect!(key, development = false, version = 1)
18
+ Base.connect!(key, development, version)
19
+ end
20
+
21
+ def self.connect_domain!(key, domain_base, version = 1)
22
+ Base.connect_domain!(key, domain_base, version)
23
+ end
24
+
25
+ def self.connect_config!(opts)
26
+ Base.connect_config!(opts)
27
+ end
28
+
29
+ # an object that stores connection details; does actual http talking
30
+ class Connection
31
+ include HTTParty
32
+ headers "accept" => "application/json"
33
+ format :json
34
+
35
+ attr_reader :key, :domain, :version, :domain_base, :ssl_port, :public_port
36
+
37
+ def initialize(key, domain_base, version, ssl_port = 443, public_port = 80)
38
+ @domain_base = domain_base
39
+ @version = version
40
+ @domain = "#{@domain_base}/v#{version}"
41
+ @key = key
42
+ @ssl_port = ssl_port
43
+ @public_port = public_port
44
+ begin # pass yaml file
45
+ key = YAML.load_file(key)
46
+ @key = key[:key] || key["key"]
47
+ rescue # pass key
48
+ @key = key
49
+ end
50
+ end
51
+
52
+ # get, post, put and delete methods
53
+ def method_missing(method_id, *args)
54
+ if [:get, :post, :put, :delete].include?(method_id)
55
+ path, options = *args
56
+ options ||= {}
57
+ options[:body] = default_params.merge(options[:body] || {})
58
+ options[:query] = (default_params.merge(options[:query] || {}))
59
+ options[:headers] = (self.class.default_options[:headers].merge(options[:headers] || {}))
60
+
61
+ self.class.send(method_id, url(path), options)
62
+ else
63
+ super
31
64
  end
32
65
  end
66
+
67
+ # Returns the base crowdflower domain from the api url's domain.
68
+ #
69
+ # @api public
70
+ # @return [String] the base crowdflower domain
71
+ # @example
72
+ # CrowdFlower::Connection.new("asdf", "https://api.crowdflower.com").crowdflower_base #=> "crowdflower.com"
73
+ def crowdflower_base
74
+ uri = URI.parse(domain_base)
75
+ "#{uri.host.gsub("api.", "")}"
76
+ end
77
+
78
+ # Returns the url to reach crowdflower regularly through a browser
79
+ #
80
+ # @api public
81
+ # @return [String] the url to reach crowdflower in a browser
82
+ # @example
83
+ # CrowdFlower::Connection.new("asdf", "https://api.crowdflower.com").public_url #=> "crowdflower.com:80"
84
+ def public_url
85
+ "#{crowdflower_base}:#{public_port}"
86
+ end
87
+
88
+ private
89
+ def url(path)
90
+ "#{@domain}/#{path}"
91
+ end
92
+
93
+ def default_params
94
+ {'key' => @key}
95
+ end
33
96
  end
34
97
 
35
- def self.connect!(key, development = false, version = 1)
36
- @@version = version
37
- @@domain = development ? "http://api.localhost.com:4000/v#{version}" : "https://api.crowdflower.com/v#{version}"
38
- @@key = key
39
- begin # pass yaml file
40
- key = YAML.load_file(key)
41
- @@key = key[:key] || key["key"]
42
- rescue # pass key
43
- @@key = key
98
+
99
+ # Base class for Crowdflower api entities.
100
+ # Now instead of one global configuration, each instance could maintain its own connection.
101
+ # If no connection is available for an instance it will look for default class-level or global
102
+ # connection settings, see Base#connection method.
103
+ # You can set class-specific connection with Base.connect! call
104
+ # for example:
105
+ # Job.connect!(api_key, development, version).
106
+ # It is possible to use several api keys simultaneously either by providing each entity instance
107
+ # with a specific Connection object or by creating entity subclasses that have their own default connections
108
+ # for example:
109
+ # CrowdFlower.connect!(default_api_key, development, version)
110
+ # (JobSubclass = Class.new(Job)).connect!(custom_api_key, development, version)
111
+ # job1 = Job.create('created with default api key')
112
+ # job2 = JobSubclass.create('created with custom api key')
113
+ class Base
114
+
115
+ def initialize(new_connection = nil)
116
+ @connection = new_connection
117
+ end
118
+
119
+ def connection
120
+ @connection or self.class.connection
121
+ end
122
+
123
+ def self.connection
124
+ default_connection or (self != Base and superclass.connection)
125
+ end
126
+
127
+ class << self
128
+ attr_accessor :default_connection
44
129
  end
45
- end
46
130
 
47
- def self.key
48
- @@key
49
- end
131
+ def self.connect!(key, development = false, version = 1)
132
+ domain_base = development ? "https://api.localdev.crowdflower.com:8443" : "https://api.crowdflower.com"
133
+ connect_domain!(key, domain_base, version)
134
+ end
135
+
136
+ def self.connect_domain!(key, domain_base, version = 1)
137
+ self.default_connection = Connection.new(key, domain_base, version)
138
+ end
139
+
140
+ def self.connect_config!(opts)
141
+ extract_option = lambda do |arr|
142
+ arr.map { |k| opts[k] || opts[k.to_s] }.compact.first
143
+ end
144
+ key = extract_option.call([:key, :api_key])
145
+ domain_base = extract_option.call([:domain_base, :domain])
146
+ version = extract_option.call([:version]) || 1
147
+ ssl_port = extract_option.call([:ssl_port]) || 443
148
+ public_port = extract_option.call([:public_port]) || 80
149
+ self.default_connection = Connection.new(key, domain_base, version, ssl_port, public_port)
150
+ end
50
151
 
51
- def self.domain
52
- @@domain
152
+ def self.get(*args); connection.get(*args); end
153
+ def self.post(*args); connection.post(*args); end
154
+ def self.put(*args); connection.put(*args); end
155
+ def self.delete(*args); connection.delete(*args); end
156
+
157
+ def connect
158
+ unless connection
159
+ raise UsageError, "Please establish a connection using 'CrowdFlower.connect!'"
160
+ end
161
+ end
162
+
163
+ def self.connect
164
+ unless connection
165
+ raise UsageError, "Please establish a connection using 'CrowdFlower.connect!'"
166
+ end
167
+ end
168
+
169
+ def self.verify_response(response)
170
+ if response["errors"]
171
+ raise CrowdFlower::APIError.new(response["errors"])
172
+ elsif response.response.kind_of? Net::HTTPUnauthorized
173
+ raise CrowdFlower::APIError.new('message' => response.to_s)
174
+ end
175
+ end
176
+
53
177
  end
178
+
54
179
  end
@@ -1,11 +1,11 @@
1
1
  module CrowdFlower
2
- class Job
3
- include Defaults
2
+ class Job < Base
4
3
  attr_reader :id
5
4
 
6
- def initialize(job_id)
5
+ def initialize(job_id, connection = nil)
6
+ super connection
7
7
  @id = job_id
8
- Job.connect
8
+ connect
9
9
  end
10
10
 
11
11
  def resource_uri
@@ -21,30 +21,30 @@ module CrowdFlower
21
21
  get(resource_uri)
22
22
  end
23
23
 
24
- def self.upload(file, content_type, job_id = nil)
24
+ def self.upload(file, content_type, job = nil)
25
25
  connect
26
- job_uri = job_id ? "/#{job_id}" : ""
27
- res = post("#{resource_uri}/#{job_uri}/upload",
26
+
27
+ job_uri = job ? "/#{job.kind_of?(Job) ? job.id : job}" : ""
28
+ conn = job.kind_of?(Job) ? job.connection : self.connection
29
+ upload_uri = "#{resource_uri}/#{job_uri}/upload".squeeze("/")
30
+ res = conn.post(upload_uri,
28
31
  :body => File.read(file),
29
- :headers => custom_content_type(content_type))
30
- if res["error"]
31
- raise CrowdFlower::APIError.new(res["error"])
32
- end
33
- Job.new(res["id"])
32
+ :headers => {"content-type" => content_type})
33
+
34
+ verify_response res
35
+ job.kind_of?(Job) ? job : self.new(res["id"], conn)
34
36
  end
35
37
 
36
38
  # Creates a new empty Job in CrowdFlower.
37
39
  def self.create(title)
38
40
  connect
39
- res = post("#{resource_uri}.json", :query => {:job => {:title => title } }, :headers => { "Content-Length" => "0" } )
40
- if res["error"]
41
- raise CrowdFlower::APIError.new(res["error"])
42
- end
43
- Job.new(res["id"])
41
+ res = self.post("#{resource_uri}.json", :query => {:job => {:title => title } }, :headers => { "Content-Length" => "0" } )
42
+ verify_response res
43
+ self.new(res["id"])
44
44
  end
45
45
 
46
46
  def get(id = nil)
47
- Job.get("#{resource_uri}/#{@id || id}")
47
+ connection.get("#{resource_uri}/#{@id || id}")
48
48
  end
49
49
 
50
50
  # Returns an accessor for all the Units associated with this job.
@@ -63,28 +63,27 @@ module CrowdFlower
63
63
  # gold: when set to true copies gold units
64
64
  # all_units: when set to true copies all units
65
65
  def copy(opts = {})
66
- res = Job.get("#{resource_uri}/#{@id}/copy", {:query => opts})
67
- if res["error"]
68
- raise CrowdFlower::APIError.new(res["error"])
69
- end
70
- Job.new(res["id"])
66
+ res = connection.get("#{resource_uri}/#{@id}/copy", {:query => opts})
67
+ self.class.verify_response res
68
+ self.class.new(res["id"])
71
69
  end
72
70
 
73
71
  def status
74
- Job.get("#{resource_uri}/#{@id}/ping")
72
+ connection.get("#{resource_uri}/#{@id}/ping")
75
73
  end
76
74
 
77
75
  def upload(file, content_type)
78
- Job.upload(file, content_type, @id)
76
+ self.class.upload(file, content_type, self)
79
77
  end
80
78
 
81
79
  def legend
82
- Job.get("#{resource_uri}/#{@id}/legend")
80
+ connection.get("#{resource_uri}/#{@id}/legend")
83
81
  end
84
82
 
85
83
  def download_csv(type = :full, filename = nil)
86
84
  filename ||= "#{type.to_s[0].chr}#{@id}.csv"
87
- res = Job.get("#{resource_uri}/#{@id}.csv", {:format => :csv, :query => {:type => type}})
85
+ res = connection.get("#{resource_uri}/#{@id}.csv", {:format => :csv, :query => {:type => type}})
86
+ self.class.verify_response res
88
87
  puts "Status... #{res.code.inspect}"
89
88
  if res.code == 202
90
89
  puts "CSV Generating... Trying again in 10 seconds."
@@ -97,40 +96,34 @@ module CrowdFlower
97
96
  end
98
97
 
99
98
  def pause
100
- Job.get("#{resource_uri}/#{@id}/pause")
99
+ connection.get("#{resource_uri}/#{@id}/pause")
101
100
  end
102
101
 
103
102
  def resume
104
- Job.get("#{resource_uri}/#{@id}/resume")
103
+ connection.get("#{resource_uri}/#{@id}/resume")
105
104
  end
106
105
 
107
106
  def cancel
108
- Job.get("#{resource_uri}/#{@id}/cancel")
107
+ connection.get("#{resource_uri}/#{@id}/cancel")
109
108
  end
110
109
 
111
110
  def update(data)
112
- res = Job.put("#{resource_uri}/#{@id}.json", {:body => { :job => data }, :headers => { "Content-Length" => "0" } } )
113
- if res["error"]
114
- raise CrowdFlower::APIError.new(res["error"])
115
- end
111
+ response = connection.put("#{resource_uri}/#{@id}.json", {:body => { :job => data }, :headers => { "Content-Length" => "0" } } )
112
+ self.class.verify_response(response)
113
+ response
116
114
  end
117
115
 
118
116
  def delete
119
- Job.delete("#{resource_uri}/#{@id}.json")
117
+ connection.delete("#{resource_uri}/#{@id}.json")
120
118
  end
121
119
 
122
120
  def channels
123
- Job.get("#{resource_uri}/#{@id}/channels")
121
+ connection.get("#{resource_uri}/#{@id}/channels")
124
122
  end
125
123
 
126
124
  def enable_channels(channels)
127
- Job.post("#{resource_uri}/#{@id}/channels", {:body => { :channels => channels } } )
125
+ connection.post("#{resource_uri}/#{@id}/channels", {:body => { :channels => channels } } )
128
126
  end
129
127
 
130
- private
131
- def self.custom_content_type(content_type)
132
- #To preserve the accept header we are forced to merge the defaults back in...
133
- Job.default_options[:headers].merge({"content-type" => content_type})
134
- end
135
128
  end
136
129
  end
@@ -1,11 +1,11 @@
1
1
  module CrowdFlower
2
- class Judgment
3
- include Defaults
2
+ class Judgment < Base
4
3
  attr_reader :job
5
4
 
6
5
  def initialize(job)
6
+ super job.connection
7
7
  @job = job
8
- Judgment.connect
8
+ connect
9
9
  end
10
10
 
11
11
  def resource_uri
@@ -13,13 +13,32 @@ module CrowdFlower
13
13
  end
14
14
 
15
15
  #Pull every judgment
16
- def all(page = 1, limit = 100, latest = true)#full = true
17
- opts = @@version == 2 ? {:unseen => latest} : {:latest => latest}
18
- Judgment.get(resource_uri, {:query => {:limit => limit, :page => page}.merge(opts)})
16
+ def all(page = 1, limit = 100, latest = true)
17
+ opts = CrowdFlower.version == 2 ? {:unseen => latest} : {:latest => latest}
18
+ get(resource_uri, {:query => {:limit => limit, :page => page}.merge(opts)})
19
19
  end
20
20
 
21
21
  def get(id)
22
- Judgment.get("/#{id}")
22
+ get("#{resource_uri}/#{id}")
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 )
31
+ put( "#{resource_uri}/#{id}/reject" )
32
+ end
33
+
34
+ protected
35
+
36
+ def put( *args )
37
+ connection.put *args
38
+ end
39
+
40
+ def get( *args )
41
+ connection.get *args
23
42
  end
24
43
  end
25
- end
44
+ end
@@ -1,11 +1,11 @@
1
1
  module CrowdFlower
2
- class Order
3
- include Defaults
2
+ class Order < Base
4
3
  attr_reader :job
5
4
 
6
5
  def initialize(job)
6
+ super job.connection
7
7
  @job = job
8
- Order.connect
8
+ connect
9
9
  end
10
10
 
11
11
  def resource_uri
@@ -13,7 +13,7 @@ module CrowdFlower
13
13
  end
14
14
 
15
15
  def debit(units_count = 1, channels = ["amt"])
16
- Order.post(resource_uri, {:query => {:debit => {:units_count => units_count}, :channels => channels}})
16
+ connection.post(resource_uri, {:query => {:debit => {:units_count => units_count}, :channels => channels}})
17
17
  end
18
18
  end
19
19
  end
@@ -1,11 +1,11 @@
1
1
  module CrowdFlower
2
- class Unit
3
- include Defaults
2
+ class Unit < Base
4
3
  attr_reader :job
5
4
 
6
5
  def initialize(job)
6
+ super job.connection
7
7
  @job = job
8
- Unit.connect
8
+ connect
9
9
  end
10
10
 
11
11
  def resource_uri
@@ -13,35 +13,35 @@ module CrowdFlower
13
13
  end
14
14
 
15
15
  def all(page = 1, limit = 1000)
16
- Unit.get(resource_uri, {:query => {:limit => limit, :page => page}})
16
+ connection.get(resource_uri, {:query => {:limit => limit, :page => page}})
17
17
  end
18
18
 
19
19
  def get(id)
20
- Unit.get("#{resource_uri}/#{id}")
20
+ connection.get("#{resource_uri}/#{id}")
21
21
  end
22
22
 
23
23
  def ping
24
- Unit.get("#{resource_uri}/ping")
24
+ connection.get("#{resource_uri}/ping")
25
25
  end
26
26
 
27
27
  def judgments(id)
28
- Unit.get("#{resource_uri}/#{id}/judgments")
28
+ connection.get("#{resource_uri}/#{id}/judgments")
29
29
  end
30
30
 
31
31
  def create(data, gold = false)
32
- Unit.post(resource_uri, {:query => {:unit => {:data => data.to_json, :golden => gold}}})
32
+ connection.post(resource_uri, {:query => {:unit => {:data => data.to_json, :golden => gold}}})
33
33
  end
34
34
 
35
35
  def copy(unit_id, job_id, data = {})
36
- Unit.get("#{resource_uri}/#{unit_id}/copy", {:query => {:unit => {:job_id => job_id, :data => data}}})
36
+ connection.get("#{resource_uri}/#{unit_id}/copy", {:query => {:unit => {:job_id => job_id, :data => data}}})
37
37
  end
38
38
 
39
39
  def split(on, with = " ")
40
- Unit.get("#{resource_uri}/split", {:query => {:on => on, :with => with}})
40
+ connection.get("#{resource_uri}/split", {:query => {:on => on, :with => with}})
41
41
  end
42
42
 
43
43
  def cancel(unit_id)
44
- Unit.post("#{resource_uri}/#{unit_id}/cancel.json")
44
+ connection.post("#{resource_uri}/#{unit_id}/cancel.json")
45
45
  end
46
46
  end
47
47
  end
@@ -0,0 +1,54 @@
1
+ module CrowdFlower
2
+ class Worker < Base
3
+ attr_reader :job
4
+
5
+ def initialize( job )
6
+ super job.connection
7
+ @job = job
8
+ connect
9
+ end
10
+
11
+ def resource_uri
12
+ "/jobs/#{@job.id}/workers"
13
+ end
14
+
15
+ def bonus( worker_id, amount, reason=nil )
16
+ params = { :amount => amount }
17
+ params.merge!( :reason => reason ) if reason
18
+ connection.put( "#{resource_uri}/#{worker_id}/bonus", :body => params )
19
+ end
20
+
21
+ def approve( worker_id )
22
+ connection.put( "#{resource_uri}/#{worker_id}/approve" )
23
+ end
24
+
25
+ def reject( worker_id )
26
+ connection.put( "#{resource_uri}/#{worker_id}/reject" )
27
+ end
28
+
29
+ def ban( worker_id )
30
+ connection.put( "#{resource_uri}/#{worker_id}/ban" )
31
+ end
32
+
33
+ def deban( worker_id )
34
+ connection.put( "#{resource_uri}/#{worker_id}/deban" )
35
+ end
36
+
37
+ def notify( worker_id, subject, message )
38
+ params = {
39
+ :subject => subject,
40
+ :message => message
41
+ }
42
+ connection.put( "#{resource_uri}/#{worker_id}/notify", :body => params )
43
+ end
44
+
45
+ def flag( worker_id, reason )
46
+ params = reason ? { :reason => reason } : nil
47
+ connection.put( "#{resource_uri}/#{worker_id}/flag", :body => params )
48
+ end
49
+
50
+ def deflag( worker_id )
51
+ connection.put( "#{resource_uri}/#{worker_id}/deflag" )
52
+ end
53
+ end
54
+ end
@@ -36,7 +36,7 @@ def wait_until
36
36
  if yield
37
37
  return
38
38
  end
39
- sleep 1
39
+ sleep 5
40
40
  end
41
41
  raise "Condition not met in a reasonable time period"
42
42
  end
@@ -47,13 +47,48 @@ def assert(truth)
47
47
  end
48
48
  end
49
49
 
50
+ def assert_exception_raised expected_exception_class
51
+ begin
52
+ yield
53
+ rescue expected_exception_class
54
+ return
55
+ end
56
+ raise "exception #{expected_ex} has not been raised"
57
+ end
58
+
59
+
50
60
  def say(msg)
51
61
  $stdout.puts msg
52
62
  end
53
63
 
64
+
65
+ say "defining multiple api keys"
66
+ (job_subclass_with_valid_custom_key = Class.new(CrowdFlower::Job)).connect! API_KEY, true
67
+ (job_subclass_with_invalid_custom_key = Class.new(CrowdFlower::Job)).connect! 'invalid api key', true
68
+ job_subclass_with_no_custom_key = Class.new(CrowdFlower::Job)
69
+
70
+ say "no default api key"
71
+ assert_exception_raised(CrowdFlower::UsageError) {CrowdFlower::Job.create("job creation should fail")}
72
+ assert_exception_raised(CrowdFlower::UsageError) {job_subclass_with_no_custom_key.create("job creation should fail")}
73
+ assert_exception_raised(CrowdFlower::APIError) {job_subclass_with_invalid_custom_key.create("job creation should fail")}
74
+ assert job_subclass_with_valid_custom_key.create("should be ok").units.ping['count']
75
+
76
+ say "invalid default api key"
77
+ CrowdFlower.connect! "invalid default api key", true
78
+ assert_exception_raised(CrowdFlower::APIError) {CrowdFlower::Job.create("job creation should fail")}
79
+ assert_exception_raised(CrowdFlower::APIError) {job_subclass_with_no_custom_key.create("job creation should fail")}
80
+ assert_exception_raised(CrowdFlower::APIError) {job_subclass_with_invalid_custom_key.create("job creation should fail")}
81
+ assert job_subclass_with_valid_custom_key.create("should be ok").units.ping['count']
82
+
54
83
  say "Connecting to the API"
55
84
  CrowdFlower.connect! API_KEY, true
56
85
 
86
+ assert CrowdFlower::Job.create("should be ok").units.ping['count']
87
+ assert job_subclass_with_no_custom_key.create("should be ok").units.ping['count']
88
+ assert job_subclass_with_valid_custom_key.create("should be ok").units.ping['count']
89
+ assert_exception_raised(CrowdFlower::APIError) {job_subclass_with_invalid_custom_key.create("job creation should fail")}
90
+ assert CrowdFlower::Base.connection.public_url == "localdev.crowdflower.com:80"
91
+
57
92
  say "Uploading a test CSV"
58
93
  job = CrowdFlower::Job.upload(File.dirname(__FILE__) + "/sample.csv", "text/csv")
59
94
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crowdflower
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
5
- prerelease: false
4
+ hash: 13
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
- - 4
9
8
  - 5
10
- version: 0.4.5
9
+ - 3
10
+ version: 0.5.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brian P O'Rourke
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-12-03 00:00:00 -08:00
19
+ date: 2011-02-10 00:00:00 -08:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -50,7 +50,6 @@ extra_rdoc_files:
50
50
  - README.md
51
51
  files:
52
52
  - .document
53
- - .gitignore
54
53
  - CONTRIBUTORS
55
54
  - HISTORY.md
56
55
  - LICENSE
@@ -66,6 +65,7 @@ files:
66
65
  - lib/crowdflower/judgment.rb
67
66
  - lib/crowdflower/order.rb
68
67
  - lib/crowdflower/unit.rb
68
+ - lib/crowdflower/worker.rb
69
69
  - test/integration_tests.rb
70
70
  - test/sample.csv
71
71
  has_rdoc: true
@@ -73,8 +73,8 @@ homepage: http://github.com/dolores/ruby-crowdflower
73
73
  licenses: []
74
74
 
75
75
  post_install_message:
76
- rdoc_options:
77
- - --charset=UTF-8
76
+ rdoc_options: []
77
+
78
78
  require_paths:
79
79
  - lib
80
80
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
98
  requirements: []
99
99
 
100
100
  rubyforge_project:
101
- rubygems_version: 1.3.7
101
+ rubygems_version: 1.4.2
102
102
  signing_key:
103
103
  specification_version: 3
104
104
  summary: a toolkit for the CrowdFlower API
data/.gitignore DELETED
@@ -1,8 +0,0 @@
1
- *.sw?
2
- .DS_Store
3
- coverage
4
- rdoc
5
- pkg
6
- tags/.loadpath
7
- /.project
8
- /.loadpath