Commit 9f0ec712f3369a626f7484d3cd24ef9acfb0e295

Authored by Dhruv Kapadia
1 parent 18da412d

Rewriting skips model, providing support

app/controllers/prompts_controller.rb
... ... @@ -53,9 +53,7 @@ class PromptsController < InheritedResources::Base
53 53 @prompt = @question.prompts.find(params[:id])
54 54  
55 55 time_viewed = params['params']['time_viewed']
56   -
57 56 visitor_identifier = params['params']['auto']
58   -
59 57 appearance_lookup = params['params']['appearance_lookup']
60 58  
61 59 case direction
... ... @@ -71,6 +69,7 @@ class PromptsController < InheritedResources::Base
71 69 respond_to do |format|
72 70 if successful
73 71 #catchup_marketplace_ids = [120, 117, 1, 116]
  72 + #TODO refactor into question model
74 73 if @question.uses_catchup?
75 74 logger.info("Question #{@question.id} is using catchup algorithm!")
76 75 next_prompt = @question.pop_prompt_queue
... ... @@ -125,12 +124,45 @@ class PromptsController < InheritedResources::Base
125 124 authenticate
126 125 logger.info "#{current_user.inspect} is skipping."
127 126 @question = Question.find(params[:question_id])
128   - @prompt = @question.prompts.find(params[:id], :include => [{ :left_choice => :item }, { :right_choice => :item }])
  127 + @prompt = @question.prompts.find(params[:id]) #, :include => [{ :left_choice => :item }, { :right_choice => :item }])
  128 +
  129 + time_viewed = params['params']['time_viewed']
  130 + raise "time_viewed cannot be nil" if time_viewed.nil?
  131 +
  132 + visitor_identifier = params['params']['auto']
  133 + raise "visitor identifier cannot be nil" if visitor_identifier.nil?
  134 + appearance_lookup = params['params']['appearance_lookup']
  135 + raise "appearance_lookup cannot be nil" if appearance_lookup.nil?
  136 +
  137 + skip_reason = params['params']['skip_reason'] # optional parameter
129 138  
130 139  
131 140 respond_to do |format|
132   - if @skip = current_user.record_skip(params['params']['auto'], @prompt)
133   - format.xml { render :xml => @question.picked_prompt.to_xml(:methods => [:left_choice_text, :right_choice_text]), :status => :ok }
  141 + if @skip = current_user.record_skip(visitor_identifier, appearance_lookup, @prompt, time_viewed, :skip_reason => skip_reason)
  142 +
  143 + if @question.uses_catchup?
  144 + logger.info("Question #{@question.id} is using catchup algorithm!")
  145 + @next_prompt = @question.pop_prompt_queue
  146 + if @next_prompt.nil?
  147 + logger.info("Catchup prompt cache miss! Nothing in prompt_queue")
  148 + @next_prompt = @question.catchup_choose_prompt
  149 + end
  150 + @question.send_later :add_prompt_to_queue
  151 + else
  152 + @next_prompt = @question.picked_prompt
  153 + end
  154 +
  155 +
  156 + visitor = current_user.visitors.find_or_create_by_identifier(visitor_identifier)
  157 + @a = current_user.record_appearance(visitor, @next_prompt)
  158 +
  159 + appearance_id = Proc.new { |options| options[:builder].tag!('appearance_id', @a.lookup) }
  160 +
  161 + visitor_votes = Proc.new { |options| options[:builder].tag!('visitor_votes', visitor.votes.count(:conditions => {:question_id => @question.id})) }
  162 + visitor_ideas = Proc.new { |options| options[:builder].tag!('visitor_ideas', visitor.items.count) }
  163 +
  164 +
  165 + format.xml { render :xml => @question.picked_prompt.to_xml(:procs => [appearance_id, visitor_votes, visitor_ideas],:methods => [:left_choice_text, :right_choice_text]), :status => :ok }
134 166 format.json { render :json => @question.picked_prompt.to_json, :status => :ok }
135 167 else
136 168 format.xml { render :xml => @skip, :status => :unprocessable_entity }
... ...
app/models/user.rb
... ... @@ -45,10 +45,9 @@ class User < ActiveRecord::Base
45 45 end
46 46  
47 47  
48   - def record_skip(visitor_identifier, prompt)
  48 + def record_skip(visitor_identifier, appearance_lookup, prompt, time_viewed, options = {})
49 49 visitor = visitors.find_or_create_by_identifier(visitor_identifier)
50   - question = prompt.question
51   - visitor.skip!(prompt)
  50 + visitor.skip!(appearance_lookup, prompt, time_viewed, options)
52 51 end
53 52  
54 53 def activate_question(question_id, options)
... ...
app/models/visitor.rb
... ... @@ -18,6 +18,7 @@ class Visitor < ActiveRecord::Base
18 18  
19 19 def vote_for!(appearance_lookup, prompt, ordinality, time_viewed)
20 20 @a = Appearance.find_by_lookup(appearance_lookup)
  21 + #make votefor fail if we cant find the appearance
21 22 choices = prompt.choices
22 23 choice = choices[ordinality] #we need to guarantee that the choices are in the right order (by position)
23 24 other_choices = choices - [choice]
... ... @@ -37,7 +38,12 @@ class Visitor < ActiveRecord::Base
37 38  
38 39 end
39 40  
40   - def skip!(prompt)
41   - prompt_skip = skips.create!(:prompt => prompt)
  41 + def skip!(appearance_lookup, prompt, time_viewed, options = {})
  42 + @a = Appearance.find_by_lookup(appearance_lookup)
  43 +
  44 + skip_create_options = { :question_id => prompt.question_id, :prompt_id => prompt.id, :skipper_id=> self.id, :time_viewed => time_viewed, :appearance_id => @a.id}
  45 +
  46 + prompt_skip = skips.create!(skip_create_options.merge(options))
  47 +
42 48 end
43 49 end
... ...
db/migrate/20100428190803_rename_skips_table.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +class RenameSkipsTable < ActiveRecord::Migration
  2 + def self.up
  3 + rename_table :skips, :oldskips
  4 + end
  5 +
  6 + def self.down
  7 + rename_table :oldskips, :skips
  8 + end
  9 +end
... ...
db/migrate/20100428190907_create_skips_model.rb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +class CreateSkipsModel < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :skips do |table|
  4 + table.text :tracking
  5 + table.integer :site_id
  6 + table.integer :skipper_id
  7 + table.integer :question_id
  8 + table.integer :prompt_id
  9 + table.integer :appearance_id
  10 + table.integer :time_viewed #msecs
  11 + table.timestamps
  12 + end
  13 +
  14 + end
  15 +
  16 + def self.down
  17 + drop_table :skips
  18 + end
  19 +end
... ...
db/migrate/20100428211749_add_skip_reason_to_skips.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +class AddSkipReasonToSkips < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :skips, :skip_reason, :string
  4 + end
  5 +
  6 + def self.down
  7 + drop_column :skips, :skip_reason
  8 + end
  9 +end
... ...
spec/controllers/prompts_controller_spec.rb
1 1 require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 2  
3 3 describe PromptsController do
  4 + def sign_in_as(user)
  5 + @controller.current_user = user
  6 + return user
  7 + end
  8 + #
  9 + before(:each) do
  10 + @aoi_clone = Factory.create(:user)
  11 + sign_in_as(@user = Factory(:email_confirmed_user))
  12 + @johndoe = Factory.create(:visitor, :identifier => 'johndoe', :site => @aoi_clone)
  13 + @question = Factory.create(:question, :name => 'which do you like better?', :site => @aoi_clone, :creator => @aoi_clone.default_visitor)
  14 + @lc = Factory.create(:choice, :question => @question, :creator => @johndoe, :data => 'hello gorgeous')
  15 + @rc = Factory.create(:choice, :question => @question, :creator => @johndoe, :data => 'goodbye gorgeous')
  16 + @prompt = Factory.create(:prompt, :question => @question, :tracking => 'sample', :left_choice => @lc, :right_choice => @rc)
  17 +
  18 + @visitor = @aoi_clone.visitors.find_or_create_by_identifier("test_visitor_identifier")
  19 + @appearance = @aoi_clone.record_appearance(@visitor, @prompt)
  20 + end
  21 + #
4 22  
5   - def mock_prompt(stubs={})
6   - @mock_prompt ||= mock_model(Prompt, stubs)
7   - end
8   -
9   - before(:each) do
10   - @aoi_clone = Factory.create(:user)
11   - @question = Factory.create(:question, :site => @aoi_clone, :creator => @aoi_clone.default_visitor)
12   - end
13   -
14   - describe "GET index" do
15   - it "assigns all prompts as @prompts" do
  23 +# describe "GET index" do
  24 +# it "assigns all prompts as @prompts" do
16 25 # Question.stub!(:find).with(:all).and_return(@question)
17 26 # Question.stub!(:prompts).with(:all).and_return([mock_prompt])
18   - get :index, :question_id => @question.id
19   - assigns[:prompts].should == [mock_prompt]
20   - end
21   - end
  27 +# get :index, :question_id => @question.id
  28 +# assigns[:prompts].should == [@prompt]
  29 +# end
  30 +# end
22 31  
23 32 describe "GET show" do
24 33 it "assigns the requested prompt as @prompt" do
25   -# Question.stub!(:find).with(:all).and_return(@question)
26   -# Prompt.stub!(:find).with("37").and_return(mock_prompt)
27   - get :show, :id => "37", :question_id => @question.id
28   - assigns[:prompt].should equal(mock_prompt)
  34 + get :show, :id => @prompt.id, :question_id => @question.id
  35 + assigns[:prompt].should == @prompt
29 36 end
30 37 end
  38 +
  39 + describe "POST skip" do
  40 + it "records a skip, responds with next prompt" do
  41 + post :skip, :id => @prompt.id, :question_id => @question.id, :params => {:auto => @visitor, :time_viewed => 30, :appearance_lookup => @appearance.lookup}
  42 + assigns[:next_prompt].should_not == @prompt
  43 + assigns[:next_prompt].should_not be_nil
  44 + assigns[:a].should_not be_nil
  45 + assigns[:a].should_not == @appearance
  46 + assigns[:skip].should_not be_nil
  47 + end
  48 + end
  49 +
31 50 end
... ...
spec/models/user_spec.rb
... ... @@ -47,7 +47,7 @@ describe User do
47 47 end
48 48  
49 49 it "should be able to record a visitor's skip" do
50   - s = @aoi_clone.record_skip("johnnydoe", @prompt)
  50 + s = @aoi_clone.record_skip("johnnydoe", @appearance.lookup, @prompt, 340)
51 51 end
52 52  
53 53 end
... ...
spec/models/visitor_spec.rb
... ... @@ -47,7 +47,7 @@ describe Visitor do
47 47 it "should be able to skip a prompt" do
48 48 #@prompt = @question.prompts.first
49 49 @prompt.should_not be_nil
50   - v = @v.skip! @prompt
  50 + v = @v.skip! @appearance.lookup, @prompt, 304
51 51 end
52 52  
53 53 it "should accurately update score counts after vote" do
... ...