Commit 14a2322e4f3dc7cca62c6edb4acae91c8269f3ec
1 parent
b36bc6f7
Exists in
master
and in
1 other branch
add votes per uploaded choice API call
Showing
7 changed files
with
79 additions
and
4 deletions
Show diff stats
CHANGELOG.md
app/controllers/questions_controller.rb
| ... | ... | @@ -98,6 +98,14 @@ class QuestionsController < InheritedResources::Base |
| 98 | 98 | end |
| 99 | 99 | end |
| 100 | 100 | |
| 101 | + def votes_per_uploaded_choice | |
| 102 | + @question = current_user.questions.find(params[:id]) | |
| 103 | + only_active = params[:only_active] == 'true' | |
| 104 | + respond_to do |format| | |
| 105 | + format.xml{ render :xml => {:value => @question.votes_per_uploaded_choice(only_active)}.to_xml and return} | |
| 106 | + end | |
| 107 | + end | |
| 108 | + | |
| 101 | 109 | def object_info_by_visitor_id |
| 102 | 110 | |
| 103 | 111 | object_type = params[:object_type] | ... | ... |
app/models/choice.rb
| ... | ... | @@ -21,6 +21,9 @@ class Choice < ActiveRecord::Base |
| 21 | 21 | has_many :skips_on_the_right, :through => :prompts_on_the_right, :source => :skips |
| 22 | 22 | named_scope :active, :conditions => { :active => true } |
| 23 | 23 | named_scope :inactive, :conditions => { :active => false} |
| 24 | + named_scope :not_created_by, lambda { |creator_id| | |
| 25 | + { :conditions => ["creator_id <> ?", creator_id] } | |
| 26 | + } | |
| 24 | 27 | |
| 25 | 28 | after_save :update_questions_counter |
| 26 | 29 | after_save :update_prompt_queue | ... | ... |
app/models/question.rb
| ... | ... | @@ -672,6 +672,16 @@ class Question < ActiveRecord::Base |
| 672 | 672 | last_appearance |
| 673 | 673 | end |
| 674 | 674 | |
| 675 | + def votes_per_uploaded_choice(only_active=false) | |
| 676 | + if only_active | |
| 677 | + uploaded_choices_count = choices.active.not_created_by(creator_id).count | |
| 678 | + else | |
| 679 | + uploaded_choices_count = choices.not_created_by(creator_id).count | |
| 680 | + end | |
| 681 | + return 0.to_f if uploaded_choices_count == 0 | |
| 682 | + votes.count.to_f / uploaded_choices_count.to_f | |
| 683 | + end | |
| 684 | + | |
| 675 | 685 | # a response is either a vote or a skip, get the median per session |
| 676 | 686 | def median_responses_per_session |
| 677 | 687 | median(Question.connection.select_values(" | ... | ... |
config/routes.rb
| ... | ... | @@ -9,6 +9,7 @@ ActionController::Routing::Routes.draw do |map| |
| 9 | 9 | :median_votes_per_session => :get, |
| 10 | 10 | :vote_rate => :get, |
| 11 | 11 | :median_responses_per_session => :get, |
| 12 | + :votes_per_uploaded_choice => :get, | |
| 12 | 13 | :upload_to_participation_ratio => :get, |
| 13 | 14 | :export => :post} , |
| 14 | 15 | :collection => {:all_num_votes_by_visitor_id => :get, | ... | ... |
spec/integration/questions_spec.rb
| ... | ... | @@ -252,6 +252,32 @@ describe "Questions" do |
| 252 | 252 | describe "GET 'object_info_totals_by_date'" do |
| 253 | 253 | end |
| 254 | 254 | |
| 255 | + describe "GET 'votes_per_uploaded_choice'" do | |
| 256 | + before(:all) { truncate_all } | |
| 257 | + it "should return the proper value" do | |
| 258 | + q = Factory.create(:aoi_question, :site => @api_user) | |
| 259 | + get_auth votes_per_uploaded_choice_question_path(q, :format => 'xml') | |
| 260 | + response.should be_success | |
| 261 | + response.body.should have_tag("value", :text => "0.0") | |
| 262 | + | |
| 263 | + get_auth votes_per_uploaded_choice_question_path(q, :format => 'xml', :only_active => true) | |
| 264 | + response.should be_success | |
| 265 | + response.body.should have_tag("value", :text => "0.0") | |
| 266 | + | |
| 267 | + v = Factory.create(:vote_new_user, :question => q) | |
| 268 | + Factory.create(:choice, :creator => v.voter, :question => q) | |
| 269 | + Factory.create(:choice, :creator => v.voter, :question => q, :active => true) | |
| 270 | + 4.times { Factory.create(:vote, :question => q, :voter => v.voter) } | |
| 271 | + get_auth votes_per_uploaded_choice_question_path(q, :format => 'xml') | |
| 272 | + response.should be_success | |
| 273 | + response.body.should have_tag("value", :text => "2.5") | |
| 274 | + | |
| 275 | + get_auth votes_per_uploaded_choice_question_path(q, :format => 'xml', :only_active => true) | |
| 276 | + response.should be_success | |
| 277 | + response.body.should have_tag("value", :text => "5.0") | |
| 278 | + end | |
| 279 | + end | |
| 280 | + | |
| 255 | 281 | describe "GET 'median_responses_per_session'" do |
| 256 | 282 | before(:all) { truncate_all } |
| 257 | 283 | it "should return the median responses per session" do | ... | ... |
spec/models/question_spec.rb
| ... | ... | @@ -249,17 +249,17 @@ describe Question do |
| 249 | 249 | (endTime - start).should < 20 |
| 250 | 250 | end |
| 251 | 251 | |
| 252 | - context "ratio of uploaded ideas to participation" do | |
| 252 | + context "median response per session" do | |
| 253 | 253 | before(:all) do |
| 254 | 254 | truncate_all |
| 255 | 255 | @q = Factory.create(:aoi_question) |
| 256 | 256 | end |
| 257 | 257 | |
| 258 | - it "should properly calculate median_responses_per_session with no responses" do | |
| 258 | + it "should properly calculate with no responses" do | |
| 259 | 259 | @q.median_responses_per_session.should == 0 |
| 260 | 260 | end |
| 261 | 261 | |
| 262 | - it "should properly calculate median_responses_per_session with 2 sessions" do | |
| 262 | + it "should properly calculate with 2 sessions" do | |
| 263 | 263 | # one session with 1 vote, one with 2 votes |
| 264 | 264 | Factory.create(:vote_new_user, :question => @q) |
| 265 | 265 | v = Factory.create(:vote_new_user, :question => @q) |
| ... | ... | @@ -267,7 +267,7 @@ describe Question do |
| 267 | 267 | @q.median_responses_per_session.should == 1.5 |
| 268 | 268 | end |
| 269 | 269 | |
| 270 | - it "should properly calculate median_responses_per_session with 3 sessions" do | |
| 270 | + it "should properly calculate with 3 sessions" do | |
| 271 | 271 | # one session with 3 skips, 2 votes |
| 272 | 272 | v = Factory.create(:vote_new_user, :question => @q) |
| 273 | 273 | 3.times { Factory.create(:skip, :question => @q, :skipper => v.voter) } |
| ... | ... | @@ -283,7 +283,33 @@ describe Question do |
| 283 | 283 | 4.times { Factory.create(:vote, :question => @q, :voter => v.voter) } |
| 284 | 284 | @q.median_responses_per_session.should == 5 |
| 285 | 285 | end |
| 286 | + end | |
| 287 | + | |
| 288 | + context "votes per uploaded choice" do | |
| 289 | + before(:all) do | |
| 290 | + truncate_all | |
| 291 | + @q = Factory.create(:aoi_question) | |
| 292 | + end | |
| 293 | + it "should be calculated properly with no uploaded choices" do | |
| 294 | + @q.votes_per_uploaded_choice.should == 0.0 | |
| 295 | + @q.votes_per_uploaded_choice(true).should == 0.0 | |
| 296 | + end | |
| 297 | + | |
| 298 | + it "should be calculated properly with some choices and votes" do | |
| 299 | + v = Factory.create(:vote_new_user, :question => @q) | |
| 300 | + Factory.create(:choice, :creator => v.voter, :question => @q) | |
| 301 | + Factory.create(:choice, :creator => v.voter, :question => @q, :active => true) | |
| 302 | + 4.times { Factory.create(:vote, :question => @q, :voter => v.voter) } | |
| 303 | + @q.votes_per_uploaded_choice.should == 2.5 | |
| 304 | + @q.votes_per_uploaded_choice(true).should == 5.0 | |
| 305 | + end | |
| 306 | + end | |
| 286 | 307 | |
| 308 | + context "ratio of uploaded ideas to participation" do | |
| 309 | + before(:all) do | |
| 310 | + truncate_all | |
| 311 | + @q = Factory.create(:aoi_question) | |
| 312 | + end | |
| 287 | 313 | it "should give proper stats required for idea:participation ratio" do |
| 288 | 314 | @q.sessions_with_uploaded_ideas.should == 0 |
| 289 | 315 | @q.sessions_with_participation.should == 0 | ... | ... |