Use stats objects instead of hashes

It will make it far easier to call other methods on the stats object,
and we're already caching the methods.

We had to remove the view fragment caching because the stats object
isn't as easy to cache. The good thing about it is the view will
automatically be updated when we change logic regarding which stats to
show, and the methods taking long to execute are cached in the model.
This commit is contained in:
Javi Martín
2019-03-18 15:38:53 +01:00
parent eba30d1585
commit 76c7827cf4
9 changed files with 244 additions and 290 deletions

View File

@@ -6,16 +6,12 @@ module Budgets
def show
authorize! :read_stats, @budget
@stats = load_stats
@stats = Budget::Stats.new(@budget)
@headings = @budget.headings.sort_by_name
end
private
def load_stats
Budget::Stats.new(@budget).generate
end
def load_budget
@budget = Budget.find_by(slug: params[:budget_id]) || Budget.find_by(id: params[:budget_id])
end

View File

@@ -33,7 +33,7 @@ class PollsController < ApplicationController
end
def stats
@stats = Poll::Stats.new(@poll).generate
@stats = Poll::Stats.new(@poll)
end
def results

View File

@@ -13,36 +13,59 @@ class Budget::Stats
User.where(id: (authors + voters + balloters + poll_ballot_voters).uniq.compact)
end
def total_participants
participants.distinct.count
end
def total_participants_support_phase
voters.uniq.count
end
def total_participants_vote_phase
(balloters + poll_ballot_voters).uniq.count
end
def total_budget_investments
budget.investments.count
end
def total_votes
budget.ballots.pluck(:ballot_lines_count).inject(0) { |sum, x| sum + x }
end
def total_selected_investments
budget.investments.selected.count
end
def total_unfeasible_investments
budget.investments.unfeasible.count
end
def headings
groups = Hash.new(0)
budget.headings.order("id ASC").each do |heading|
groups[heading.id] = Hash.new(0).merge(calculate_heading_totals(heading))
end
groups[:total] = Hash.new(0)
groups[:total][:total_investments_count] = groups.collect {|_k, v| v[:total_investments_count]}.sum
groups[:total][:total_participants_support_phase] = groups.collect {|_k, v| v[:total_participants_support_phase]}.sum
groups[:total][:total_participants_vote_phase] = groups.collect {|_k, v| v[:total_participants_vote_phase]}.sum
groups[:total][:total_participants_all_phase] = groups.collect {|_k, v| v[:total_participants_all_phase]}.sum
budget.headings.each do |heading|
groups[heading.id].merge!(calculate_heading_stats_with_totals(groups[heading.id], groups[:total], heading.population))
end
groups[:total][:percentage_participants_support_phase] = groups.collect {|_k, v| v[:percentage_participants_support_phase]}.sum
groups[:total][:percentage_participants_vote_phase] = groups.collect {|_k, v| v[:percentage_participants_vote_phase]}.sum
groups[:total][:percentage_participants_all_phase] = groups.collect {|_k, v| v[:percentage_participants_all_phase]}.sum
groups
end
private
def total_participants
participants.distinct.count
end
def total_participants_support_phase
voters.uniq.count
end
def total_participants_vote_phase
(balloters + poll_ballot_voters).uniq.count
end
def total_budget_investments
budget.investments.count
end
def total_votes
budget.ballots.pluck(:ballot_lines_count).inject(0) { |sum, x| sum + x }
end
def total_selected_investments
budget.investments.selected.count
end
def total_unfeasible_investments
budget.investments.unfeasible.count
end
def authors
budget.investments.pluck(:author_id)
end
@@ -71,29 +94,6 @@ class Budget::Stats
end
end
def headings
groups = Hash.new(0)
budget.headings.order("id ASC").each do |heading|
groups[heading.id] = Hash.new(0).merge(calculate_heading_totals(heading))
end
groups[:total] = Hash.new(0)
groups[:total][:total_investments_count] = groups.collect {|_k, v| v[:total_investments_count]}.sum
groups[:total][:total_participants_support_phase] = groups.collect {|_k, v| v[:total_participants_support_phase]}.sum
groups[:total][:total_participants_vote_phase] = groups.collect {|_k, v| v[:total_participants_vote_phase]}.sum
groups[:total][:total_participants_all_phase] = groups.collect {|_k, v| v[:total_participants_all_phase]}.sum
budget.headings.each do |heading|
groups[heading.id].merge!(calculate_heading_stats_with_totals(groups[heading.id], groups[:total], heading.population))
end
groups[:total][:percentage_participants_support_phase] = groups.collect {|_k, v| v[:percentage_participants_support_phase]}.sum
groups[:total][:percentage_participants_vote_phase] = groups.collect {|_k, v| v[:percentage_participants_vote_phase]}.sum
groups[:total][:percentage_participants_all_phase] = groups.collect {|_k, v| v[:percentage_participants_all_phase]}.sum
groups
end
def calculate_heading_totals(heading)
{
total_investments_count: heading.investments.count,

View File

@@ -9,7 +9,7 @@ module Statisticable
end
def generate
self.class.stats_methods.map { |stat_name| [stat_name, send(stat_name)] }.to_h
self.class.stats_methods.each { |stat_name| send(stat_name) }
end
def total_male_participants

View File

@@ -8,158 +8,156 @@
social_description: @budget.description_finished %>
<% end %>
<% cache [@stats] do %>
<div class="participation-stats budgets-stats">
<div class="expanded no-margin-top padding header">
<div class="row">
<div class="small-12 column">
<%= back_link_to budgets_path %>
<h2 class="margin-top">
<%= t("stats.title") %><br>
<span><%= @budget.name %></span>
</h2>
</div>
</div>
</div>
<div class="row margin-top">
<div class="participation-stats budgets-stats">
<div class="expanded no-margin-top padding header">
<div class="row">
<div class="small-12 column">
<ul class="tabs">
<li class="tabs-title">
<span class="show-for-sr"><%= t("shared.you_are_in") %></span>
<%= link_to t("budgets.results.link"), budget_results_path(@budget) %>
</li>
<li class="tabs-title is-active">
<%= link_to t("stats.budgets.link"), budget_stats_path(@budget), class: "is-active" %>
</li>
<li class="tabs-title">
<%= link_to t("budgets.executions.link"), budget_executions_path(@budget) %>
</li>
</ul>
<%= back_link_to budgets_path %>
<h2 class="margin-top">
<%= t("stats.title") %><br>
<span><%= @budget.name %></span>
</h2>
</div>
</div>
</div>
<div class="row margin">
<div class="small-12 medium-3 column sidebar">
<%= render "shared/stats/links" %>
<div class="row margin-top">
<div class="small-12 column">
<ul class="tabs">
<li class="tabs-title">
<span class="show-for-sr"><%= t("shared.you_are_in") %></span>
<%= link_to t("budgets.results.link"), budget_results_path(@budget) %>
</li>
<li class="tabs-title is-active">
<%= link_to t("stats.budgets.link"), budget_stats_path(@budget), class: "is-active" %>
</li>
<li class="tabs-title">
<%= link_to t("budgets.executions.link"), budget_executions_path(@budget) %>
</li>
</ul>
</div>
</div>
<p><strong><%= link_to t("stats.advanced"), "#advanced_statistics" %></strong></p>
<ul class="menu vertical">
<li>
<%= link_to t("stats.budgets.total_investments"), "#total_investments"%>
</li>
<li>
<%= link_to t("stats.budgets.by_phase"), "#stats_by_phase"%>
</li>
<li>
<%= link_to t("stats.budgets.by_heading"), "#stats_by_heading"%>
</li>
</ul>
</div>
<div class="row margin">
<div class="small-12 medium-3 column sidebar">
<%= render "shared/stats/links" %>
<div class="small-12 medium-9 column stats-content">
<%= render "shared/stats/participation", stats: @stats %>
<p><strong><%= link_to t("stats.advanced"), "#advanced_statistics" %></strong></p>
<ul class="menu vertical">
<li>
<%= link_to t("stats.budgets.total_investments"), "#total_investments" %>
</li>
<li>
<%= link_to t("stats.budgets.by_phase"), "#stats_by_phase" %>
</li>
<li>
<%= link_to t("stats.budgets.by_heading"), "#stats_by_heading" %>
</li>
</ul>
</div>
<div id="advanced_statistics">
<h3 class="section-title"><%= t("stats.advanced") %></h3>
<div class="small-12 medium-9 column stats-content">
<%= render "shared/stats/participation", stats: @stats %>
<div id="total_investments" class="stats-group">
<h4><%= t("stats.budgets.total_investments") %></h4>
<div id="advanced_statistics">
<h3 class="section-title"><%= t("stats.advanced") %></h3>
<%= number_with_info_tags(
@stats[:total_budget_investments],
t("stats.budgets.total_investments"),
html_class: "total-investments"
) %>
<div id="total_investments" class="stats-group">
<h4><%= t("stats.budgets.total_investments") %></h4>
<%= number_with_info_tags(@stats[:total_unfeasible_investments],
t("stats.budgets.total_unfeasible_investments")) %>
<%= number_with_info_tags(@stats[:total_selected_investments],
t("stats.budgets.total_selected_investments")) %>
</div>
<%= number_with_info_tags(
@stats.total_budget_investments,
t("stats.budgets.total_investments"),
html_class: "total-investments"
) %>
<div id="stats_by_phase" class="stats-group">
<h4><%= t("stats.budgets.by_phase") %></h4>
<%= number_with_info_tags(@stats[:total_participants_support_phase],
t("stats.budgets.participants_support_phase")) %>
<%= number_with_info_tags(@stats[:total_participants_vote_phase],
t("stats.budgets.participants_voting_phase")) %>
</div>
<div id="stats_by_heading" class="stats-group">
<h4 class="margin-bottom"><%= t("stats.budgets.by_heading") %></h4>
<table class="stats-districts survey-districts">
<thead>
<tr>
<th scope="col" rowspan="2"><%= t("stats.budgets.heading") %></th>
<th scope="col" rowspan="2"><%= t("stats.budgets.investments_sent_html") %></th>
<th scope="col" colspan="3"><%= t("stats.budgets.participants_support_phase") %></th>
<th scope="col" colspan="3"><%= t("stats.budgets.participants_voting_phase") %></th>
<th scope="col" colspan="3"><%= t("stats.budgets.participants_total") %></th>
</tr>
<tr>
<th scope="col" class="tiny"><%= t("stats.budgets.total") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_total_participants_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_heading_census_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.total") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_total_participants_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_heading_census_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.total") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_total_participants_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_heading_census_html") %></th>
</tr>
</thead>
<tbody id="headings">
<% @headings.each do |heading| %>
<tr id="<%= heading.name.parameterize %>">
<td class="border-left">
<strong><%= heading.name %></strong>
</td>
<td id="total_spending_proposals_heading_<%= heading.id %>"
class="text-center border-left border-right">
<%= @stats[:headings][heading.id][:total_investments_count] %>
</td>
<% ["support", "vote", "all"].each do |phase| %>
<td id="total_participants_<%= phase %>_phase_heading_<%= heading.id %>"
class="border-left text-center">
<%= @stats[:headings][heading.id]["total_participants_#{phase}_phase".to_sym] %>
</td>
<td id="percentage_participants_<%= phase %>_phase_heading_<%= heading.id %>"
class="border-left border-right text-center">
<%= number_to_stats_percentage(@stats[:headings][heading.id]["percentage_participants_#{phase}_phase".to_sym]) %>
</td>
<td id="percentage_district_population_<%= phase %>_phase_heading_<%= heading.id %>"
class="text-center border-right">
<%= number_to_stats_percentage(@stats[:headings][heading.id]["percentage_district_population_#{phase}_phase".to_sym]) %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
</div>
<%= number_with_info_tags(@stats.total_unfeasible_investments,
t("stats.budgets.total_unfeasible_investments")) %>
<%= number_with_info_tags(@stats.total_selected_investments,
t("stats.budgets.total_selected_investments")) %>
</div>
<div class="row margin">
<div class="small-12 column">
<div id="total_unknown_gender_or_age">
<p class="help-text">
<%= t("stats.budgets.no_demographic_data", total: @stats[:total_unknown_gender_or_age]) %>
</p>
<p class="help-text">
<%= t("stats.budgets.participatory_disclaimer") %>
</p>
<p class="help-text">
<%= t("stats.budgets.heading_disclaimer") %>
</p>
</div>
<div id="stats_by_phase" class="stats-group">
<h4><%= t("stats.budgets.by_phase") %></h4>
<%= number_with_info_tags(@stats.total_participants_support_phase,
t("stats.budgets.participants_support_phase")) %>
<%= number_with_info_tags(@stats.total_participants_vote_phase,
t("stats.budgets.participants_voting_phase")) %>
</div>
<div id="stats_by_heading" class="stats-group">
<h4 class="margin-bottom"><%= t("stats.budgets.by_heading") %></h4>
<table class="stats-districts survey-districts">
<thead>
<tr>
<th scope="col" rowspan="2"><%= t("stats.budgets.heading") %></th>
<th scope="col" rowspan="2"><%= t("stats.budgets.investments_sent_html") %></th>
<th scope="col" colspan="3"><%= t("stats.budgets.participants_support_phase") %></th>
<th scope="col" colspan="3"><%= t("stats.budgets.participants_voting_phase") %></th>
<th scope="col" colspan="3"><%= t("stats.budgets.participants_total") %></th>
</tr>
<tr>
<th scope="col" class="tiny"><%= t("stats.budgets.total") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_total_participants_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_heading_census_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.total") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_total_participants_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_heading_census_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.total") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_total_participants_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_heading_census_html") %></th>
</tr>
</thead>
<tbody id="headings">
<% @headings.each do |heading| %>
<tr id="<%= heading.name.parameterize %>">
<td class="border-left">
<strong><%= heading.name %></strong>
</td>
<td id="total_spending_proposals_heading_<%= heading.id %>"
class="text-center border-left border-right">
<%= @stats.headings[heading.id][:total_investments_count] %>
</td>
<% ["support", "vote", "all"].each do |phase| %>
<td id="total_participants_<%= phase %>_phase_heading_<%= heading.id %>"
class="border-left text-center">
<%= @stats.headings[heading.id]["total_participants_#{phase}_phase".to_sym] %>
</td>
<td id="percentage_participants_<%= phase %>_phase_heading_<%= heading.id %>"
class="border-left border-right text-center">
<%= number_to_stats_percentage(@stats.headings[heading.id]["percentage_participants_#{phase}_phase".to_sym]) %>
</td>
<td id="percentage_district_population_<%= phase %>_phase_heading_<%= heading.id %>"
class="text-center border-right">
<%= number_to_stats_percentage(@stats.headings[heading.id]["percentage_district_population_#{phase}_phase".to_sym]) %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
<div class="row margin">
<div class="small-12 column">
<div id="total_unknown_gender_or_age">
<p class="help-text">
<%= t("stats.budgets.no_demographic_data", total: @stats.total_unknown_gender_or_age) %>
</p>
<p class="help-text">
<%= t("stats.budgets.participatory_disclaimer") %>
</p>
<p class="help-text">
<%= t("stats.budgets.heading_disclaimer") %>
</p>
</div>
</div>
</div>
</div>
</div>
<% end %>
</div>

View File

@@ -31,9 +31,9 @@
<% Poll::Stats::CHANNELS.each do |channel| %>
<%= number_with_info_tags(
@stats[:"total_participants_#{channel}"],
@stats.send("total_participants_#{channel}"),
t("stats.polls.#{channel}_percentage",
percentage: number_to_stats_percentage(@stats[:"total_participants_#{channel}_percentage"])
percentage: number_to_stats_percentage(@stats.send(:"total_participants_#{channel}_percentage"))
),
html_class: channel
) %>
@@ -59,14 +59,14 @@
<% Poll::Stats::CHANNELS.each do |channel| %>
<td>
<%= @stats[:"total_#{channel}_valid"] %>
<small><em>(<%= @stats[:"valid_percentage_#{channel}"].round(2) %>%)</em></small>
<%= @stats.send(:"total_#{channel}_valid") %>
<small><em>(<%= @stats.send(:"valid_percentage_#{channel}").round(2) %>%)</em></small>
</td>
<% end %>
<td>
<%= @stats[:total_valid_votes] %>
<small><em>(<%= @stats[:total_valid_percentage].round(2) %>%)</em></small>
<%= @stats.total_valid_votes %>
<small><em>(<%= @stats.total_valid_percentage.round(2) %>%)</em></small>
</td>
</tr>
@@ -75,13 +75,13 @@
<% Poll::Stats::CHANNELS.each do |channel| %>
<td>
<%= @stats[:"total_#{channel}_white"] %>
<small><em>(<%= @stats[:"white_percentage_#{channel}"].round(2) %>%)</em></small>
<%= @stats.send(:"total_#{channel}_white") %>
<small><em>(<%= @stats.send(:"white_percentage_#{channel}").round(2) %>%)</em></small>
</td>
<% end %>
<td><%= @stats[:total_white_votes] %>
<small><em>(<%= @stats[:total_white_percentage].round(2) %>%)</em></small>
<td><%= @stats.total_white_votes %>
<small><em>(<%= @stats.total_white_percentage.round(2) %>%)</em></small>
</td>
</tr>
<tr>
@@ -89,14 +89,14 @@
<% Poll::Stats::CHANNELS.each do |channel| %>
<td>
<%= @stats[:"total_#{channel}_null"] %>
<small><em>(<%= @stats[:"null_percentage_#{channel}"].round(2) %>%)</em></small>
<%= @stats.send(:"total_#{channel}_null") %>
<small><em>(<%= @stats.send(:"null_percentage_#{channel}").round(2) %>%)</em></small>
</td>
<% end %>
<td>
<%= @stats[:total_null_votes] %>
<small><em>(<%= @stats[:total_null_percentage].round(2) %>%)</em></small>
<%= @stats.total_null_votes %>
<small><em>(<%= @stats.total_null_percentage.round(2) %>%)</em></small>
</td>
</tr>
<tr>
@@ -104,12 +104,12 @@
<% Poll::Stats::CHANNELS.each do |channel| %>
<td>
<%= @stats[:"total_participants_#{channel}"] %>
<small><em>(<%= @stats[:"total_participants_#{channel}_percentage"].round(2) %>%)</em></small>
<%= @stats.send(:"total_participants_#{channel}") %>
<small><em>(<%= @stats.send(:"total_participants_#{channel}_percentage").round(2) %>%)</em></small>
</td>
<% end %>
<td><%= @stats[:total_participants] %></td>
<td><%= @stats.total_participants %></td>
</tr>
</tbody>
</table>

View File

@@ -5,7 +5,7 @@
<h4><%= t("stats.total_participants") %></h4>
<%= number_with_info_tags(
stats[:total_participants],
stats.total_participants,
"",
html_class: "participants total-participants"
) %>
@@ -15,14 +15,14 @@
<h4><%= t("stats.by_gender") %></h4>
<%= number_with_info_tags(
stats[:total_male_participants],
t("stats.men_percentage", percentage: number_to_stats_percentage(stats[:male_percentage])),
stats.total_male_participants,
t("stats.men_percentage", percentage: number_to_stats_percentage(stats.male_percentage)),
html_class: "participants male"
) %>
<%= number_with_info_tags(
stats[:total_female_participants],
t("stats.women_percentage", percentage: number_to_stats_percentage(stats[:female_percentage])),
stats.total_female_participants,
t("stats.women_percentage", percentage: number_to_stats_percentage(stats.female_percentage)),
html_class: "participants female"
) %>
</div>
@@ -39,7 +39,7 @@
</thead>
<tbody>
<% stats[:participants_by_age].values.each do |group| %>
<% stats.participants_by_age.values.each do |group| %>
<tr>
<td><%= group[:range] %></td>
<td>
@@ -70,7 +70,7 @@
</thead>
<tbody>
<% stats[:participants_by_geozone].each do |geozone, participants| %>
<% stats.participants_by_geozone.each do |geozone, participants| %>
<tr>
<td><%= geozone %></td>
<td><%= "#{participants[:total][:count]} (#{number_to_stats_percentage(participants[:total][:percentage])})" %></td>

View File

@@ -33,7 +33,7 @@ describe Budget::Stats do
expect(stats.participants).to match_array(
[author, author_and_voter, voter, voter_and_balloter, balloter, poll_balloter]
)
expect(stats.generate[:total_participants]).to be 6
expect(stats.total_participants).to be 6
end
end
@@ -42,7 +42,7 @@ describe Budget::Stats do
2.times { create(:vote, votable: investment) }
create(:budget_ballot_line, investment: investment)
expect(stats.generate[:total_participants_support_phase]).to be 2
expect(stats.total_participants_support_phase).to be 2
end
it "counts a user who is voter and balloter" do
@@ -50,7 +50,7 @@ describe Budget::Stats do
create(:vote, votable: investment, voter: voter_and_balloter)
create(:budget_ballot_line, investment: investment, user: voter_and_balloter)
expect(stats.generate[:total_participants_support_phase]).to be 1
expect(stats.total_participants_support_phase).to be 1
end
end
@@ -59,7 +59,7 @@ describe Budget::Stats do
2.times { create(:budget_ballot_line, investment: investment) }
create(:vote, votable: investment)
expect(stats.generate[:total_participants_vote_phase]).to be 2
expect(stats.total_participants_vote_phase).to be 2
end
it "counts a user who is voter and balloter" do
@@ -67,14 +67,14 @@ describe Budget::Stats do
create(:vote, votable: investment, voter: voter_and_balloter)
create(:budget_ballot_line, investment: investment, user: voter_and_balloter)
expect(stats.generate[:total_participants_vote_phase]).to be 1
expect(stats.total_participants_vote_phase).to be 1
end
it "includes balloters and poll balloters" do
create(:budget_ballot_line, investment: investment)
create(:poll_voter, :from_booth, budget: budget)
expect(stats.generate[:total_participants_vote_phase]).to be 2
expect(stats.total_participants_vote_phase).to be 2
end
it "counts once a user who is balloter and poll balloter" do
@@ -82,7 +82,7 @@ describe Budget::Stats do
create(:budget_ballot_line, investment: investment, user: poller_and_balloter)
create(:poll_voter, :from_booth, user: poller_and_balloter, budget: budget)
expect(stats.generate[:total_participants_vote_phase]).to be 1
expect(stats.total_participants_vote_phase).to be 1
end
it "doesn't count nil user ids" do
@@ -90,7 +90,7 @@ describe Budget::Stats do
ballot: create(:budget_ballot, budget: budget, user: nil, physical: true)
)
expect(stats.generate[:total_participants_vote_phase]).to be 0
expect(stats.total_participants_vote_phase).to be 0
end
end
@@ -99,7 +99,7 @@ describe Budget::Stats do
2.times { create(:budget_investment, budget: budget) }
create(:budget_investment, budget: create(:budget))
expect(stats.generate[:total_budget_investments]).to be 2
expect(stats.total_budget_investments).to be 2
end
end
@@ -108,7 +108,7 @@ describe Budget::Stats do
create(:budget_ballot_line, investment: investment)
create(:budget_ballot_line, investment: create(:budget_investment, :selected, budget: budget))
expect(stats.generate[:total_votes]).to be 2
expect(stats.total_votes).to be 2
end
end
@@ -118,7 +118,7 @@ describe Budget::Stats do
create(:budget_investment, :selected, budget: create(:budget))
create(:budget_investment, :unfeasible, budget: budget)
expect(stats.generate[:total_selected_investments]).to be 3
expect(stats.total_selected_investments).to be 3
end
end
@@ -128,7 +128,7 @@ describe Budget::Stats do
create(:budget_investment, :unfeasible, budget: create(:budget))
create(:budget_investment, :selected, budget: budget)
expect(stats.generate[:total_unfeasible_investments]).to be 3
expect(stats.total_unfeasible_investments).to be 3
end
end
@@ -143,31 +143,31 @@ describe Budget::Stats do
describe "#total_male_participants" do
it "returns the number of total male participants" do
expect(stats.generate[:total_male_participants]).to be 3
expect(stats.total_male_participants).to be 3
end
end
describe "#total_female_participants" do
it "returns the number of total female participants" do
expect(stats.generate[:total_female_participants]).to be 2
expect(stats.total_female_participants).to be 2
end
end
describe "#total_unknown_gender_or_age" do
it "returns the number of total unknown participants' gender or age" do
expect(stats.generate[:total_unknown_gender_or_age]).to be 1
expect(stats.total_unknown_gender_or_age).to be 1
end
end
describe "#male_percentage" do
it "returns the percentage of male participants" do
expect(stats.generate[:male_percentage]).to be 60.0
expect(stats.male_percentage).to be 60.0
end
end
describe "#female_percentage" do
it "returns the percentage of female participants" do
expect(stats.generate[:female_percentage]).to be 40.0
expect(stats.female_percentage).to be 40.0
end
end
end
@@ -182,18 +182,18 @@ describe Budget::Stats do
end
it "returns the age groups hash" do
expect(stats.generate[:participants_by_age]["16 - 19"][:count]).to be 0
expect(stats.generate[:participants_by_age]["20 - 24"][:count]).to be 4
expect(stats.generate[:participants_by_age]["25 - 29"][:count]).to be 0
expect(stats.generate[:participants_by_age]["30 - 34"][:count]).to be 1
expect(stats.generate[:participants_by_age]["35 - 39"][:count]).to be 0
expect(stats.generate[:participants_by_age]["40 - 44"][:count]).to be 3
expect(stats.generate[:participants_by_age]["45 - 49"][:count]).to be 0
expect(stats.generate[:participants_by_age]["50 - 54"][:count]).to be 2
expect(stats.generate[:participants_by_age]["55 - 59"][:count]).to be 0
expect(stats.generate[:participants_by_age]["60 - 64"][:count]).to be 0
expect(stats.generate[:participants_by_age]["65 - 69"][:count]).to be 0
expect(stats.generate[:participants_by_age]["70 - 74"][:count]).to be 0
expect(stats.participants_by_age["16 - 19"][:count]).to be 0
expect(stats.participants_by_age["20 - 24"][:count]).to be 4
expect(stats.participants_by_age["25 - 29"][:count]).to be 0
expect(stats.participants_by_age["30 - 34"][:count]).to be 1
expect(stats.participants_by_age["35 - 39"][:count]).to be 0
expect(stats.participants_by_age["40 - 44"][:count]).to be 3
expect(stats.participants_by_age["45 - 49"][:count]).to be 0
expect(stats.participants_by_age["50 - 54"][:count]).to be 2
expect(stats.participants_by_age["55 - 59"][:count]).to be 0
expect(stats.participants_by_age["60 - 64"][:count]).to be 0
expect(stats.participants_by_age["65 - 69"][:count]).to be 0
expect(stats.participants_by_age["70 - 74"][:count]).to be 0
end
end
@@ -206,7 +206,7 @@ describe Budget::Stats do
end
it "returns headings data" do
heading_stats = stats.generate[:headings][investment.heading.id]
heading_stats = stats.headings[investment.heading.id]
expect(heading_stats[:total_investments_count]).to be 2
expect(heading_stats[:total_participants_support_phase]).to be 2
expect(heading_stats[:total_participants_vote_phase]).to be 1

View File

@@ -183,44 +183,4 @@ describe Poll::Stats do
expect(stats.participants_by_geozone["Midgar"][:percentage]).to eq(33.333)
end
end
describe "#generate" do
it "generates the correct stats" do
poll = create(:poll)
2.times { create(:poll_voter, :from_web, poll: poll) }
3.times { create(:poll_voter, :from_booth, poll: poll) }
create(:poll_recount, :from_booth, poll: poll,
white_amount: 1, null_amount: 0, total_amount: 2)
stats = Poll::Stats.new(poll).generate
expect(stats[:total_participants]).to eq(5)
expect(stats[:total_participants_web]).to eq(2)
expect(stats[:total_participants_booth]).to eq(3)
expect(stats[:total_valid_votes]).to eq(4)
expect(stats[:total_white_votes]).to eq(1)
expect(stats[:total_null_votes]).to eq(0)
expect(stats[:total_web_valid]).to eq(2)
expect(stats[:total_web_white]).to eq(0)
expect(stats[:total_web_null]).to eq(0)
expect(stats[:total_booth_valid]).to eq(2)
expect(stats[:total_booth_white]).to eq(1)
expect(stats[:total_booth_null]).to eq(0)
expect(stats[:total_participants_web_percentage]).to eq(40)
expect(stats[:total_participants_booth_percentage]).to eq(60)
expect(stats[:valid_percentage_web]).to eq(50)
expect(stats[:white_percentage_web]).to eq(0)
expect(stats[:null_percentage_web]).to eq(0)
expect(stats[:valid_percentage_booth]).to eq(50)
expect(stats[:white_percentage_booth]).to eq(100)
expect(stats[:null_percentage_booth]).to eq(0)
expect(stats[:total_valid_percentage]).to eq(80)
expect(stats[:total_white_percentage]).to eq(20)
expect(stats[:total_null_percentage]).to eq(0)
end
end
end
end