turkee 1.2.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.document +5 -0
  2. data/.gitignore +27 -0
  3. data/Gemfile.lock +124 -0
  4. data/Guardfile +12 -0
  5. data/README.rdoc +53 -21
  6. data/VERSION +1 -0
  7. data/lib/generators/turkee/templates/create_turkee_study.rb.erb +18 -0
  8. data/lib/generators/turkee/turkee_generator.rb +4 -0
  9. data/lib/helpers/turkee_forms_helper.rb +68 -0
  10. data/lib/models/turkee_imported_assignment.rb +15 -0
  11. data/lib/models/turkee_study.rb +11 -0
  12. data/lib/models/turkee_task.rb +257 -0
  13. data/lib/tasks/turkee.rb +13 -1
  14. data/lib/turkee.rb +4 -317
  15. data/spec/dummy/Rakefile +7 -0
  16. data/spec/dummy/app/assets/javascripts/application.js +5 -0
  17. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  18. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  19. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  20. data/spec/dummy/app/mailers/.gitkeep +0 -0
  21. data/spec/dummy/app/models/.gitkeep +0 -0
  22. data/spec/dummy/app/views/layouts/application.html.erb +19 -0
  23. data/spec/dummy/config.ru +4 -0
  24. data/spec/dummy/config/application.rb +41 -0
  25. data/spec/dummy/config/boot.rb +10 -0
  26. data/spec/dummy/config/database.yml +25 -0
  27. data/spec/dummy/config/environment.rb +5 -0
  28. data/spec/dummy/config/environments/development.rb +27 -0
  29. data/spec/dummy/config/environments/production.rb +54 -0
  30. data/spec/dummy/config/environments/test.rb +39 -0
  31. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  32. data/spec/dummy/config/initializers/inflections.rb +10 -0
  33. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  34. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  35. data/spec/dummy/config/initializers/session_store.rb +8 -0
  36. data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
  37. data/spec/dummy/config/locales/en.yml +5 -0
  38. data/spec/dummy/config/routes.rb +62 -0
  39. data/spec/dummy/db/migrate/20110710143903_initial_tables.rb +23 -0
  40. data/spec/dummy/db/migrate/20120819164528_add_association_with_class_name.rb +12 -0
  41. data/spec/dummy/db/migrate/20130203095901_create_company.rb +14 -0
  42. data/spec/dummy/db/schema.rb +45 -0
  43. data/spec/dummy/public/404.html +26 -0
  44. data/spec/dummy/public/422.html +26 -0
  45. data/spec/dummy/public/500.html +26 -0
  46. data/spec/dummy/public/favicon.ico +0 -0
  47. data/spec/dummy/script/rails +6 -0
  48. data/spec/dummy/tmp/cache/.gitkeep +0 -0
  49. data/spec/factories/turkee_task_factory.rb +21 -0
  50. data/spec/helpers/turkee_forms_helper_spec.rb +44 -0
  51. data/spec/models/turkee_study_spec.rb +19 -0
  52. data/spec/{turkee_spec.rb → models/turkee_task_spec.rb} +0 -0
  53. data/spec/spec_helper.rb +21 -6
  54. data/turkee.gemspec +59 -0
  55. metadata +69 -21
@@ -0,0 +1,11 @@
1
+ module Turkee
2
+ class TurkeeStudy < ActiveRecord::Base
3
+ GOLD_RESPONSE_INDEX = 3
4
+ attr_accessible :turkee_task_id, :feedback, :gold_response
5
+
6
+ def approve?
7
+ words = feedback.split(/\W+/)
8
+ gold_response.present? ? (gold_response == words[GOLD_RESPONSE_INDEX]) : true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,257 @@
1
+ require 'rubygems'
2
+ require 'socket'
3
+ require 'rturk'
4
+ require 'lockfile'
5
+ require 'active_record'
6
+ require "active_support/core_ext/object/to_query"
7
+ require 'action_controller'
8
+
9
+ module Turkee
10
+
11
+ class TurkeeTask < ActiveRecord::Base
12
+ attr_accessible :sandbox, :hit_title, :hit_description, :hit_reward, :hit_num_assignments, :hit_lifetime, :hit_duration,
13
+ :form_url, :hit_url, :hit_id, :task_type, :complete
14
+
15
+ HIT_FRAMEHEIGHT = 1000
16
+
17
+ scope :unprocessed_hits, lambda { where('complete = ? AND sandbox = ?', false, RTurk.sandbox?) }
18
+
19
+ # Use this method to go out and retrieve the data for all of the posted Turk Tasks.
20
+ # Each specific TurkeeTask object (determined by task_type field) is in charge of
21
+ # accepting/rejecting the assignment and importing the data into their respective tables.
22
+ def self.process_hits(turkee_task = nil)
23
+
24
+ begin
25
+ # Using a lockfile to prevent multiple calls to Amazon.
26
+ Lockfile.new('/tmp/turk_processor.lock', :max_age => 3600, :retries => 10) do
27
+
28
+ turks = task_items(turkee_task)
29
+
30
+ turks.each do |turk|
31
+ hit = RTurk::Hit.new(turk.hit_id)
32
+
33
+ callback_models = Set.new
34
+ hit.assignments.each do |assignment|
35
+ next unless submitted?(assignment.status)
36
+ next if assignment_exists?(assignment)
37
+
38
+ model, param_hash = map_imported_values(assignment, turk.task_type)
39
+ next if model.nil?
40
+
41
+ callback_models << model
42
+
43
+ result = save_imported_values(model, param_hash)
44
+
45
+ # If there's a custom approve? method, see if we should approve the submitted assignment
46
+ # otherwise just approve it by default
47
+ turk.process_result(assignment, result)
48
+
49
+ TurkeeImportedAssignment.record_imported_assignment(assignment, result, turk)
50
+ end
51
+
52
+ turk.set_expired?(callback_models) if !turk.set_complete?(hit, callback_models)
53
+ end
54
+ end
55
+ rescue Lockfile::MaxTriesLockError => e
56
+ logger.info "TurkTask.process_hits is already running or the lockfile /tmp/turk_processor.lock exists from an improperly shutdown previous process. Exiting method call."
57
+ end
58
+
59
+ end
60
+
61
+ def self.save_imported_values(model, param_hash)
62
+ key = model.to_s.underscore.gsub('/','_') # Namespaced model will come across as turkee/turkee_study,
63
+ # we must translate to turkee_turkee_study"
64
+ model.create(param_hash[key])
65
+ end
66
+
67
+ # Creates a new Mechanical Turk task on AMZN with the given title, desc, etc
68
+ def self.create_hit(host, hit_title, hit_description, typ, num_assignments, reward, lifetime,
69
+ duration = nil, qualifications = {}, params = {}, opts = {})
70
+ model = typ.to_s.constantize
71
+ f_url = build_url(host, model, params, opts)
72
+
73
+ h = RTurk::Hit.create(:title => hit_title) do |hit|
74
+ hit.assignments = num_assignments
75
+ hit.description = hit_description
76
+ hit.reward = reward
77
+ hit.lifetime = lifetime.to_i.days.seconds.to_i
78
+ hit.duration = duration.to_i.hours.seconds.to_i if duration
79
+ hit.question(f_url, :frame_height => HIT_FRAMEHEIGHT)
80
+ unless qualifications.empty?
81
+ qualifications.each do |key, value|
82
+ hit.qualifications.add key, value
83
+ end
84
+ end
85
+ end
86
+
87
+ TurkeeTask.create(:sandbox => RTurk.sandbox?,
88
+ :hit_title => hit_title, :hit_description => hit_description,
89
+ :hit_reward => reward.to_f, :hit_num_assignments => num_assignments.to_i,
90
+ :hit_lifetime => lifetime, :hit_duration => duration,
91
+ :form_url => f_url, :hit_url => h.url,
92
+ :hit_id => h.id, :task_type => typ,
93
+ :complete => false)
94
+
95
+ end
96
+
97
+ ##########################################################################################################
98
+ # DON'T PUSH THIS BUTTON UNLESS YOU MEAN IT. :)
99
+ def self.clear_all_turks(force = false)
100
+ # Do NOT execute this function if we're in production mode
101
+ raise "You can only clear turks in the sandbox/development environment unless you pass 'true' for the force flag." if Rails.env == 'production' && !force
102
+
103
+ hits = RTurk::Hit.all
104
+
105
+ logger.info "#{hits.size} reviewable hits. \n"
106
+
107
+ unless hits.empty?
108
+ logger.info "Approving all assignments and disposing of each hit."
109
+
110
+ hits.each do |hit|
111
+ begin
112
+ hit.expire!
113
+ hit.assignments.each do |assignment|
114
+ logger.info "Assignment status : #{assignment.status}"
115
+ assignment.approve!('__clear_all_turks__approved__') if assignment.status == 'Submitted'
116
+ end
117
+
118
+ turkee_task = TurkeeTask.find_by_hit_id(hit.id)
119
+ turkee_task.complete_task
120
+
121
+ hit.dispose!
122
+ rescue Exception => e
123
+ # Probably a service unavailable
124
+ logger.error "Exception : #{e.to_s}"
125
+ end
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ def complete_task
132
+ self.complete = true
133
+ save!
134
+ end
135
+
136
+ def set_complete?(hit, models)
137
+ if completed_assignments?
138
+ hit.dispose!
139
+ complete_task
140
+ initiate_callback(:hit_complete, models)
141
+ return true
142
+ end
143
+
144
+ false
145
+ end
146
+
147
+ def set_expired?(models)
148
+ if expired?
149
+ self.expired = true
150
+ save!
151
+ initiate_callback(:hit_expired, models)
152
+ end
153
+ end
154
+
155
+ def initiate_callback(method, models)
156
+ models.each { |model| model.send(method, self) if model.respond_to?(method) }
157
+ end
158
+
159
+ def process_result(assignment, result)
160
+ if result.errors.size > 0
161
+ logger.info "Errors : #{result.inspect}"
162
+ assignment.reject!('Failed to enter proper data.')
163
+ elsif result.respond_to?(:approve?)
164
+ logger.debug "Approving : #{result.inspect}"
165
+ self.increment_complete_assignments
166
+ result.approve? ? assignment.approve!('') : assignment.reject!('Rejected criteria.')
167
+ else
168
+ self.increment_complete_assignments
169
+ assignment.approve!('')
170
+ end
171
+ end
172
+
173
+ def increment_complete_assignments
174
+ raise "Missing :completed_assignments attribute. Please upgrade Turkee to the most recent version." unless respond_to?(:completed_assignments)
175
+
176
+ self.completed_assignments += 1
177
+ save
178
+ end
179
+
180
+ private
181
+
182
+ def logger
183
+ @logger ||= Logger.new($stderr)
184
+ end
185
+
186
+ def self.map_imported_values(assignment, default_type)
187
+ params = assignment_params(assignment.answers)
188
+ param_hash = Rack::Utils.parse_nested_query(params)
189
+
190
+ model = find_model(param_hash)
191
+ model = default_type.constantize if model.nil?
192
+
193
+ return model, param_hash
194
+ end
195
+
196
+ def self.assignment_exists?(assignment)
197
+ TurkeeImportedAssignment.find_by_assignment_id(assignment.id).present?
198
+ end
199
+
200
+ def completed_assignments?
201
+ completed_assignments == hit_num_assignments
202
+ end
203
+
204
+ def expired?
205
+ Time.now >= (created_at + hit_lifetime.days)
206
+ end
207
+
208
+ def self.task_items(turkee_task)
209
+ turkee_task.nil? ? TurkeeTask.unprocessed_hits : Array.new << turkee_task
210
+ end
211
+
212
+ def self.submitted?(status)
213
+ (status == 'Submitted')
214
+ end
215
+
216
+ def self.assignment_params(answers)
217
+ answers.to_query
218
+ end
219
+
220
+ # Method looks at the parameter and attempts to find an ActiveRecord model
221
+ # in the current app that would match the properties of one of the nested hashes
222
+ # x = {:submit = 'Create', :iteration_vote => {:iteration_id => 1}}
223
+ # The above _should_ return an IterationVote model
224
+ def self.find_model(param_hash)
225
+ param_hash.each do |k, v|
226
+ if v.is_a?(Hash)
227
+ model = k.to_s.camelize.constantize rescue next
228
+ return model if model.descends_from_active_record? rescue next
229
+ end
230
+ end
231
+ nil
232
+ end
233
+
234
+ # Returns custom URL if opts[:form_url] is specified. Otherwise, builds the default url from the model's :new route
235
+ def self.build_url(host, model, params, opts)
236
+ if opts[:form_url]
237
+ full_url(opts[:form_url], params)
238
+ else
239
+ form_url(host, model, params)
240
+ end
241
+ end
242
+
243
+ # Returns the default url of the model's :new route
244
+ def self.form_url(host, typ, params = {})
245
+ @app ||= ActionController::Integration::Session.new(Rails.application)
246
+ url = (host + @app.send("new_#{typ.to_s.underscore}_path"))
247
+ full_url(url, params)
248
+ end
249
+
250
+ # Appends params to the url as a query string
251
+ def self.full_url(u, params)
252
+ url = u
253
+ url = "#{u}?#{params.to_query}" unless params.empty?
254
+ url
255
+ end
256
+ end
257
+ end
data/lib/tasks/turkee.rb CHANGED
@@ -6,7 +6,7 @@ namespace :turkee do
6
6
  task :post_hit, [:host, :title, :description, :model, :num_assignments, :reward, :lifetime] => :environment do |t, args|
7
7
  hit = Turkee::TurkeeTask.create_hit(args[:host],args[:title], args[:description], args[:model],
8
8
  args[:num_assignments], args[:reward], args[:lifetime])
9
- puts "Hit created ( #{hit.hit_url} )."
9
+ puts "Hit created : #{hit.hit_url}"
10
10
  end
11
11
 
12
12
  desc "Retrieve all results from Mechanical Turk for all open HITs."
@@ -14,4 +14,16 @@ namespace :turkee do
14
14
  Turkee::TurkeeTask.process_hits
15
15
  end
16
16
 
17
+ desc "Create a usability study. Task takes the application's full url, HIT title, HIT description, model name, number of responses, reward for each response, number of days the HIT should be valid, and number of hours a worker has to complete the HIT."
18
+ task :create_study, [:url, :title, :description, :num_assignments, :reward, :lifetime] => :environment do |t, args|
19
+ qualifications = {:approval_rate => {:gt => 70}, :country => {:eql => 'US'}}
20
+
21
+ hit = Turkee::TurkeeTask.create_hit(args[:url], args[:title], args[:description], "Turkee::TurkeeStudy",
22
+ args[:num_assignments], args[:reward], args[:lifetime],
23
+ nil, qualifications, {}, {:form_url => args[:url]})
24
+ puts
25
+ puts "Study created : #{hit.hit_url}"
26
+ end
27
+
28
+
17
29
  end
data/lib/turkee.rb CHANGED
@@ -1,321 +1,8 @@
1
1
  require 'rubygems'
2
- require 'socket'
3
- require 'rturk'
4
- require 'lockfile'
5
- require 'active_record'
6
2
  require 'action_view'
7
- require "active_support/core_ext/object/to_query"
8
- require 'action_controller'
9
-
10
- module Turkee
11
-
12
- # Model simply tracks what assignments have been imported
13
- class TurkeeImportedAssignment < ActiveRecord::Base
14
- attr_accessible :assignment_id, :turkee_task_id, :worker_id, :result_id
15
-
16
- def self.record_imported_assignment(assignment, result, turk)
17
- TurkeeImportedAssignment.create!(:assignment_id => assignment.id,
18
- :turkee_task_id => turk.id,
19
- :worker_id => assignment.worker_id,
20
- :result_id => result.id)
21
- end
22
-
23
- end
24
-
25
- class TurkeeTask < ActiveRecord::Base
26
- attr_accessible :sandbox, :hit_title, :hit_description, :hit_reward, :hit_num_assignments, :hit_lifetime, :hit_duration,
27
- :form_url, :hit_url, :hit_id, :task_type, :complete
28
-
29
- HIT_FRAMEHEIGHT = 1000
30
-
31
- scope :unprocessed_hits, lambda{ where('complete = ? AND sandbox = ?', false, RTurk.sandbox?) }
32
-
33
- # Use this method to go out and retrieve the data for all of the posted Turk Tasks.
34
- # Each specific TurkeeTask object (determined by task_type field) is in charge of
35
- # accepting/rejecting the assignment and importing the data into their respective tables.
36
- def self.process_hits(turkee_task = nil)
37
-
38
- begin
39
- # Using a lockfile to prevent multiple calls to Amazon.
40
- Lockfile.new('/tmp/turk_processor.lock', :max_age => 3600, :retries => 10) do
41
-
42
- turks = task_items(turkee_task)
43
-
44
- turks.each do |turk|
45
- hit = RTurk::Hit.new(turk.hit_id)
46
-
47
- callback_models = Set.new
48
- hit.assignments.each do |assignment|
49
- next unless submitted?(assignment.status)
50
- next if assignment_exists?(assignment)
51
-
52
- model, param_hash = map_imported_values(assignment)
53
- next if model.nil?
54
-
55
- callback_models << model
56
-
57
- result = save_imported_values(model, param_hash)
58
-
59
- # If there's a custom approve? method, see if we should approve the submitted assignment
60
- # otherwise just approve it by default
61
- turk.process_result(assignment, result)
62
-
63
- TurkeeImportedAssignment.record_imported_assignment(assignment, result, turk)
64
- end
65
-
66
- turk.set_expired?(callback_models) if !turk.set_complete?(hit, callback_models)
67
- end
68
- end
69
- rescue Lockfile::MaxTriesLockError => e
70
- logger.info "TurkTask.process_hits is already running or the lockfile /tmp/turk_processor.lock exists from an improperly shutdown previous process. Exiting method call."
71
- end
72
-
73
- end
74
-
75
- def self.save_imported_values(model, param_hash)
76
- model.create(param_hash[model.to_s.underscore])
77
- end
78
-
79
- # Creates a new Mechanical Turk task on AMZN with the given title, desc, etc
80
- def self.create_hit(host, hit_title, hit_description, typ, num_assignments, reward, lifetime, duration = nil, qualifications = {}, params = {}, opts = {})
81
- model = typ.to_s.constantize
82
- f_url = build_url(host, model, params, opts)
83
-
84
- h = RTurk::Hit.create(:title => hit_title) do |hit|
85
- hit.assignments = num_assignments
86
- hit.description = hit_description
87
- hit.reward = reward
88
- hit.lifetime = lifetime.to_i.days.seconds.to_i
89
- hit.duration = duration.to_i.hours.seconds.to_i if duration
90
- hit.question(f_url, :frame_height => HIT_FRAMEHEIGHT)
91
- unless qualifications.empty?
92
- qualifications.each do |key, value|
93
- hit.qualifications.add key, value
94
- end
95
- end
96
- end
97
-
98
- TurkeeTask.create(:sandbox => RTurk.sandbox?,
99
- :hit_title => hit_title, :hit_description => hit_description,
100
- :hit_reward => reward.to_f, :hit_num_assignments => num_assignments.to_i,
101
- :hit_lifetime => lifetime, :hit_duration => duration,
102
- :form_url => f_url, :hit_url => h.url,
103
- :hit_id => h.id, :task_type => typ,
104
- :complete => false)
105
-
106
- end
107
-
108
- ##########################################################################################################
109
- # DON'T PUSH THIS BUTTON UNLESS YOU MEAN IT. :)
110
- def self.clear_all_turks(force = false)
111
- # Do NOT execute this function if we're in production mode
112
- raise "You can only clear turks in the sandbox/development environment unless you pass 'true' for the force flag." if Rails.env == 'production' && !force
113
-
114
- hits = RTurk::Hit.all
115
-
116
- logger.info "#{hits.size} reviewable hits. \n"
117
-
118
- unless hits.empty?
119
- logger.info "Approving all assignments and disposing of each hit."
120
-
121
- hits.each do |hit|
122
- begin
123
- hit.expire!
124
- hit.assignments.each do |assignment|
125
- logger.info "Assignment status : #{assignment.status}"
126
- assignment.approve!('__clear_all_turks__approved__') if assignment.status == 'Submitted'
127
- end
128
-
129
- turkee_task = TurkeeTask.find_by_hit_id(hit.id)
130
- turkee_task.complete_task
131
-
132
- hit.dispose!
133
- rescue Exception => e
134
- # Probably a service unavailable
135
- logger.error "Exception : #{e.to_s}"
136
- end
137
- end
138
- end
139
-
140
- end
141
-
142
- def complete_task
143
- self.complete = true
144
- save!
145
- end
146
-
147
- def set_complete?(hit, models)
148
- if completed_assignments?
149
- hit.dispose!
150
- complete_task
151
- initiate_callback(:hit_complete, models)
152
- return true
153
- end
154
-
155
- false
156
- end
157
-
158
- def set_expired?(models)
159
- if expired?
160
- self.expired = true
161
- save!
162
- initiate_callback(:hit_expired, models)
163
- end
164
- end
165
-
166
- def initiate_callback(method, models)
167
- models.each { |model| model.send(method, self) if model.respond_to?(method) }
168
- end
169
-
170
- def process_result(assignment, result)
171
- if result.errors.size > 0
172
- logger.info "Errors : #{result.inspect}"
173
- assignment.reject!('Failed to enter proper data.')
174
- elsif result.respond_to?(:approve?)
175
- logger.debug "Approving : #{result.inspect}"
176
- self.increment_complete_assignments
177
- result.approve? ? assignment.approve!('') : assignment.reject!('Rejected criteria.')
178
- else
179
- self.increment_complete_assignments
180
- assignment.approve!('')
181
- end
182
- end
183
-
184
- def increment_complete_assignments
185
- raise "Missing :completed_assignments attribute. Please upgrade Turkee to the most recent version." unless respond_to?(:completed_assignments)
186
-
187
- self.completed_assignments += 1
188
- save
189
- end
190
-
191
- private
192
-
193
- def logger
194
- @logger ||= Logger.new($stderr)
195
- end
196
-
197
- def self.map_imported_values(assignment)
198
- params = assignment_params(assignment.answers)
199
- param_hash = Rack::Utils.parse_nested_query(params)
200
- return find_model(param_hash), param_hash
201
- end
202
-
203
- def self.assignment_exists?(assignment)
204
- TurkeeImportedAssignment.find_by_assignment_id(assignment.id).present?
205
- end
206
-
207
- def completed_assignments?
208
- completed_assignments == hit_num_assignments
209
- end
210
-
211
- def expired?
212
- Time.now >= (created_at + hit_lifetime.days)
213
- end
214
-
215
- def self.task_items(turkee_task)
216
- turkee_task.nil? ? TurkeeTask.unprocessed_hits : Array.new << turkee_task
217
- end
218
-
219
- def self.submitted?(status)
220
- (status == 'Submitted')
221
- end
222
-
223
- def self.assignment_params(answers)
224
- answers.to_query
225
- end
226
-
227
- # Method looks at the parameter and attempts to find an ActiveRecord model
228
- # in the current app that would match the properties of one of the nested hashes
229
- # x = {:submit = 'Create', :iteration_vote => {:iteration_id => 1}}
230
- # The above _should_ return an IterationVote model
231
- def self.find_model(param_hash)
232
- param_hash.each do |k, v|
233
- if v.is_a?(Hash)
234
- model = k.to_s.camelize.constantize rescue next
235
- return model if model.descends_from_active_record? rescue next
236
- end
237
- end
238
- nil
239
- end
240
-
241
- # Returns custom URL if opts[:form_url] is specified. Otherwise, builds the default url from the model's :new route
242
- def self.build_url(host, model, params, opts)
243
- if opts[:form_url]
244
- full_url(opts[:form_url], params)
245
- else
246
- form_url(host, model, params)
247
- end
248
- end
249
-
250
- # Returns the default url of the model's :new route
251
- def self.form_url(host, typ, params = {})
252
- @app ||= ActionController::Integration::Session.new(Rails.application)
253
- url = (host + @app.send("new_#{typ.to_s.underscore}_path"))
254
- full_url(url, params)
255
- end
256
-
257
- # Appends params to the url as a query string
258
- def self.full_url(u, params)
259
- url = u
260
- url = "#{u}?#{params.to_query}" unless params.empty?
261
- url
262
- end
263
-
264
- end
265
-
266
-
267
- module TurkeeFormHelper
268
-
269
- # Rails 3.1.1 form_for implementation with the exception of the form action url
270
- # will always point to the Amazon externalSubmit interface and you must pass in the
271
- # assignment_id parameter.
272
- def turkee_form_for(record, params, options = {}, &proc)
273
- raise ArgumentError, "Missing block" unless block_given?
274
- raise ArgumentError, "turkee_form_for now requires that you pass in the entire params hash, instead of just the assignmentId value. " unless params.is_a?(Hash)
275
- options[:html] ||= {}
276
-
277
- case record
278
- when String, Symbol
279
- object_name = record
280
- object = nil
281
- else
282
- object = record.is_a?(Array) ? record.last : record
283
- object_name = options[:as] || ActiveModel::Naming.param_key(object)
284
- apply_form_for_options!(record, options)
285
- end
286
-
287
- options[:html][:remote] = options.delete(:remote) if options.has_key?(:remote)
288
- options[:html][:method] = options.delete(:method) if options.has_key?(:method)
289
- options[:html][:authenticity_token] = options.delete(:authenticity_token)
290
-
291
- builder = options[:parent_builder] = instantiate_builder(object_name, object, options, &proc)
292
- fields_for = fields_for(object_name, object, options, &proc)
293
- default_options = builder.multipart? ? { :multipart => true } : {}
294
-
295
- output = form_tag(mturk_url, default_options.merge!(options.delete(:html)))
296
- params.each do |k,v|
297
- unless k =~ /^action$/i || k =~ /^controller$/i || v.class != String
298
- output.safe_concat("<input type=\"hidden\" id=\"#{k}\" name=\"#{CGI.escape(k)}\" value=\"#{CGI.escape(v)}\"/>")
299
- end
300
- end
301
- options[:disabled] = true if params[:assignmentId].nil? || Turkee::TurkeeFormHelper::disable_form_fields?(params[:assignmentId])
302
- output << fields_for
303
- output.safe_concat('</form>')
304
- end
305
-
306
- # Returns the external Mechanical Turk url used to post form data based on whether RTurk is cofigured
307
- # for sandbox use or not.
308
- def mturk_url
309
- RTurk.sandbox? ? "https://workersandbox.mturk.com/mturk/externalSubmit" : "https://www.mturk.com/mturk/externalSubmit"
310
- end
311
-
312
- # Returns whether the form fields should be disabled or not (based on the assignment_id)
313
- def self.disable_form_fields?(assignment)
314
- assignment_id = assignment.is_a?(Hash) ? assignment[:assignmentId] : assignment
315
- (assignment_id.nil? || assignment_id == 'ASSIGNMENT_ID_NOT_AVAILABLE')
316
- end
317
- end
318
-
319
- end
3
+ require 'helpers/turkee_forms_helper'
4
+ require 'models/turkee_imported_assignment'
5
+ require 'models/turkee_task'
6
+ require 'models/turkee_study'
320
7
 
321
8
  ActionView::Base.send :include, Turkee::TurkeeFormHelper