Permalink
Browse files

HIT expiration is now signaled by it's own callback on the model (hit…

…_expired)
  • Loading branch information...
1 parent 40d4db1 commit 8d523e8cc9981bb80d8bf0474b06c75b238aafcc @aantix committed Oct 13, 2012
View
@@ -5,18 +5,6 @@ Seamlessly convert your Rails forms for use on Mechanical Turk. Then, easily im
External forms are created using a simple form helper. HITs are created by issuing a rake command. Retrieving submitted response data and importing that data into your model(s) requires just one more rake command.
-== Rails 2
-
-I'm no longer supporting Rails 2.x. If you have Rails 2 changes, message me and we can look to maintaing a Rails 2.x branch.
-
-
-== Mechanical Turk API Changes
-
-Mechanical Turk is now requiring that the hitId, workerId, and the turkSubmitTo parameters be passed in along with the assignmentId and form parameters.
-
-What does this mean for you? Not much besides the fact that now when you construct your forms using turkee_form_for, you'll be passing in your entire params hash instead of just the assignment_id. The code snippet below reflect this change.
-
-
== Install/Upgrade
Add turkee to your Gemfile as a gem dependency, then do a 'bundle install':
@@ -131,6 +119,14 @@ As for Mechanical Turk approval, if the row is created and you haven't specified
end
end
+9) If all of specified assignments for a HIT have not been completed by the end of the HITs lifetime, Turkee will attempt to call the optional hit_expired class method for the model. This can be used for any cleanup logic. E.g. :
+ class Survey < ActiveRecord::Base
+ def self.hit_expired(turkee_task)
+ #do something
+ end
+ end
+
+
== Advanced Usage
1) You can use the params hash to pass object IDs to your forms. E.g. if you wanted to setup a form of questions about a given URL (let's call the model UrlSurvey), your code would look something like :
@@ -0,0 +1,15 @@
+class AddExpired < ActiveRecord::Migration
+
+ def self.up
+ unless column_exists? :turkee_tasks, :expired
+ add_column :turkee_tasks, :expired, :integer
+ end
+ end
+
+ def self.down
+ if column_exists? :turkee_tasks, :expired
+ remove_column :turkee_tasks, :expired
+ end
+ end
+end
+
@@ -34,6 +34,10 @@ def create_migrations
migration_template "add_hit_duration.rb.erb", "db/migrate/add_hit_duration.rb"
+ sleep 1
+
+ migration_template "add_expired.rb.erb", "db/migrate/add_expired.rb"
+
end
def create_initializer
View
@@ -63,7 +63,7 @@ def self.process_hits(turkee_task = nil)
TurkeeImportedAssignment.record_imported_assignment(assignment, result, turk)
end
- turk.check_hit_completeness(hit, callback_models)
+ turk.set_expired?(callback_models) if !turk.set_complete?(hit, callback_models)
end
end
rescue Lockfile::MaxTriesLockError => e
@@ -145,20 +145,30 @@ def self.clear_all_turks(force = false)
end
- def check_hit_completeness(hit, models)
- logger.debug "#### completed_assignments == hit_num_assignments :: #{self.completed_assignments} == #{self.hit_num_assignments}"
- if completed_assignments? || expired?
+ def set_complete?(hit, models)
+ if completed_assignments?
hit.dispose!
self.complete = true
save!
- initiate_hit_complete_callback(models)
+ initiate_callback(:hit_complete, models)
+ return true
+ end
+
+ false
+ end
+
+ def set_expired?(models)
+ if expired?
+ self.expired = true
+ save!
+ initiate_callback(:hit_expired, models)
end
end
- def initiate_hit_complete_callback(models)
- models.each { |model| model.hit_complete(turk) if model.respond_to?(:hit_complete) }
+ def initiate_callback(method, models)
+ models.each { |model| model.send(method, self) if model.respond_to?(method) }
end
def process_result(assignment, result)
@@ -13,7 +13,8 @@
s.hit_lifetime 1
s.hit_duration 1
s.form_url "http://localhost/test_task/new"
- s.complete true
+ s.complete false
+ s.expired false
s.created_at Time.now
s.updated_at Time.now
end
View
@@ -24,11 +24,16 @@
t.string "form_url"
t.integer "completed_assignments", :default => 0
t.boolean "complete"
+ t.boolean "expired"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "turkee_flow_id"
t.integer "hit_duration"
end
+
+ create_table :surveys do |t|
+ t.string :answer
+ end
end
View
@@ -2,10 +2,22 @@
describe Turkee::TurkeeTask do
class TestTask < ActiveRecord::Base
- def self.abstract_class; true; end
+ def self.abstract_class
+ true
+ end
+
attr_accessor :description
end
+ class Survey < ActiveRecord::Base
+ def self.abstract_class
+ true
+ end
+
+ def self.hit_complete(hit)
+ end
+ end
+
describe ".completed_assignments?" do
it "is not complete" do
turkee_task = FactoryGirl.create(:turkee_task)
@@ -33,6 +45,80 @@ def self.abstract_class; true; end
end
end
+ describe ".set_complete?" do
+ before do
+ @hit = RTurk::Hit.new(123)
+ end
+ context "completed hits" do
+ before do
+ @turkee_task = FactoryGirl.create(:turkee_task,
+ :hit_num_assignments => 100,
+ :completed_assignments => 100)
+ end
+
+ it "marks the turkee task as complete" do
+ @hit.should_receive(:dispose!).once
+ Survey.should_receive(:hit_complete).once
+ @turkee_task.set_complete?(@hit, [Survey])
+ @turkee_task.complete.should be_true
+ end
+ end
+
+ context "incomplete hits" do
+ before do
+ @turkee_task = FactoryGirl.create(:turkee_task,
+ :hit_num_assignments => 99,
+ :completed_assignments => 100)
+ end
+
+ it "keeps the turkee task as incomplete" do
+ @hit.should_not_receive(:dispose!)
+ Survey.should_not_receive(:hit_complete)
+ @turkee_task.set_complete?(@hit, [Survey]).should be_false
+ @turkee_task.complete.should be_false
+ end
+ end
+ end
+
+ describe ".set_expired?" do
+ context "unexpired hits" do
+ before do
+ @turkee_task = FactoryGirl.create(:turkee_task)
+ end
+
+ it "keeps the turkee task as unexpired" do
+ Survey.should_not_receive(:hit_expired)
+ @turkee_task.set_expired?([Survey])
+ @turkee_task.expired.should be_false
+ end
+ end
+
+ context "expired hits" do
+ before do
+ @turkee_task = FactoryGirl.create(:turkee_task,
+ :created_at => 2.days.ago,
+ :hit_lifetime => 1)
+ end
+
+ it "marks the turkee task as expired" do
+ Survey.should_receive(:hit_expired)
+ @turkee_task.set_expired?([Survey]).should be_true
+ @turkee_task.expired.should be_true
+ end
+ end
+ end
+
+ describe ".initiate_callback" do
+ before do
+ @turkee_task = FactoryGirl.create(:turkee_task)
+ end
+ it "calls hit_complete for the given callback model" do
+ Survey.should_receive(:hit_complete).once
+ @turkee_task.initiate_callback(:hit_complete, [Survey])
+ end
+
+ end
+
describe "#find_model" do
it "should return a turkee_task mode " do
returned_data = {:submit => 'Create', "test_task" => {:description => "desc"}}
@@ -44,7 +130,7 @@ def self.abstract_class; true; end
Turkee::TurkeeTask.find_model(returned_data).should be_nil
end
end
-
+
describe "#assignment_params" do
it "should encode the params properly" do
answers = {:test => "abc", :test2 => "this is a test"}
View
@@ -1,8 +1,3 @@
-# Generated by jeweler
-# DO NOT EDIT THIS FILE DIRECTLY
-# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
-# -*- encoding: utf-8 -*-
-
Gem::Specification.new do |s|
s.name = %q{turkee}
s.version = "1.2.1"
@@ -25,6 +20,7 @@ Gem::Specification.new do |s|
"lib/generators/turkee/templates/turkee_migration.rb.erb",
"lib/generators/turkee/templates/add_imported_assignment_details.rb.erb",
"lib/generators/turkee/templates/add_hit_duration.rb.erb",
+ "lib/generators/turkee/templates/add_expired.rb.erb",
"lib/generators/turkee/turkee_generator.rb",
"lib/tasks/turkee.rb",
"lib/turkee.rb",

0 comments on commit 8d523e8

Please sign in to comment.