Skip to content

Commit 1a096cc

Browse files
committed
add API call for median votes per session
1 parent bfb34f2 commit 1a096cc

File tree

6 files changed

+50
-1
lines changed

6 files changed

+50
-1
lines changed

app/controllers/questions_controller.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,13 @@ def export
8484
# export_format = params[:export_format] #CSV always now, could expand to xml later
8585
end
8686

87+
def median_votes_per_session
88+
@question = current_user.questions.find(params[:id])
89+
respond_to do |format|
90+
format.xml{ render :xml => {:median => @question.median_votes_per_session}.to_xml and return}
91+
end
92+
end
93+
8794
def object_info_by_visitor_id
8895

8996
object_type = params[:object_type]

app/models/question.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
class Question < ActiveRecord::Base
22
require 'set'
3+
include Utility
34
extend ActiveSupport::Memoizable
45

56
belongs_to :creator, :class_name => "Visitor", :foreign_key => "creator_id"
@@ -50,7 +51,17 @@ def create_choices_from_ideas
5051
def item_count
5152
choices.size
5253
end
53-
54+
55+
# returns array of hashes where each has has voter_id and total keys
56+
def votes_per_session
57+
self.votes.find(:all, :select => 'voter_id, count(*) as total', :group => :voter_id).map { |v| {:voter_id => v.voter_id, :total => v.total.to_i} }
58+
end
59+
60+
def median_votes_per_session
61+
totals = self.votes_per_session.map { |v| v[:total] }
62+
return median(totals)
63+
end
64+
5465
def choose_prompt(options = {})
5566

5667
# if there is one or fewer active choices, we won't be able to find a prompt

config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
map.resources :questions, :except => [:edit, :destroy],
77
:member => {:object_info_totals_by_date => :get,
88
:object_info_by_visitor_id => :get,
9+
:median_votes_per_session => :get,
910
:export => :post} ,
1011
:collection => {:all_num_votes_by_visitor_id => :get,
1112
:all_object_info_totals_by_date => :get,

lib/utility.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module Utility
2+
def mean(array)
3+
array.inject(0) { |sum, x| sum += x } / array.size.to_f
4+
end
5+
6+
def median(array, already_sorted=false)
7+
return nil if array.empty?
8+
array = array.sort unless already_sorted
9+
m_pos = array.size / 2
10+
return array.size % 2 == 1 ? array[m_pos] : mean(array[m_pos-1..m_pos])
11+
end
12+
end

spec/integration/questions_spec.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
end
1111
end
1212

13+
describe "GET 'median_votes_per_session'" do
14+
it "should return the median" do
15+
Factory.create(:vote, :question => @questions.first)
16+
get_auth median_votes_per_session_question_path(@questions.first, :format => 'xml')
17+
response.should be_success
18+
response.body.should have_tag("median", :text => "1")
19+
end
20+
end
21+
1322
describe "GET 'index'" do
1423
it "should return an array of questions" do
1524
get_auth questions_path(:format => 'xml')

spec/models/question_spec.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@
2222
@question.choices.active.reload.size.should == 2
2323
end
2424

25+
it "should report median votes per session" do
26+
aoiquestion = Factory.create(:aoi_question)
27+
prompt = aoiquestion.prompts.first
28+
Factory.create(:vote, :question => aoiquestion, :prompt => prompt)
29+
Factory.create(:vote, :question => aoiquestion, :prompt => prompt)
30+
aoiquestion.votes_per_session.should == [{:voter_id => aoiquestion.creator.id, :total => 2}]
31+
aoiquestion.median_votes_per_session.should == 2
32+
end
33+
2534
it "should create a new instance given valid attributes" do
2635
# Factory.attributes_for does not return associations, this is a good enough substitute
2736
Question.create!(Factory.build(:question).attributes.symbolize_keys)

0 commit comments

Comments
 (0)