-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hxl stats view 145 147 #180
Changes from 22 commits
505fc25
024f664
4d54556
f31ddf3
cc492d2
a7f42be
b6709ba
4fa5948
f9c11db
5abb632
6a0542b
e379e8a
2f6449a
058e291
0cbc42f
a0ea11a
bfb52b7
0447c5d
15c4541
96cc7b9
9e46293
40234d2
5766dc6
93be3a7
b2353dc
ac24ae8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
class HxlstatsController < ApplicationController | ||
def show | ||
@results = HxlStatsView.results_by_emotional_state | ||
|
||
respond_to do |format| | ||
format.html | ||
format.json { send_data @results, filename: "hxlstats-#{Date.today}.json" } | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
class HxlStatsView < ActiveRecord::Base | ||
# View aggregates data in a multi-nested-group by for the HXL proxy/endpoint | ||
# | ||
self.table_name = 'hxl_stats_view' | ||
def readonly? | ||
true | ||
end | ||
|
||
HXLSTATS_COLUMN_HEADERS = | ||
["Emotional State", | ||
"Stage of journey", | ||
"Country drawn in", | ||
"Total children affected", | ||
"Children who identify as female", | ||
"Children who identify as male", | ||
"Children who identify as neither female nor male", | ||
"Children between the ages of 5-12", | ||
"Children between the ages of 13-18", | ||
"Children under 5 years old", | ||
"Older than 18 years old"].freeze | ||
|
||
HXL_STATS_TAGS = | ||
["#impact+indicator+code", | ||
"#affected+children", | ||
"#country+code", | ||
"#affected+children+total", | ||
"#affected+children+female", | ||
"#affected+children+male", | ||
"#affected+children+other_gender", | ||
"#affected+children+age_5_12", | ||
"#affected+children+age_13_18", | ||
"#affected+children+age_under5", | ||
"#affected+children+age_18plus"].freeze | ||
|
||
private_class_method :get_counts_by_gender | ||
private_class_method :get_counts_by_age | ||
|
||
def self.get_counts_by_gender(hxlstatsmajorgroup) | ||
# Group by gender and aggregate | ||
gender_totals = Hash.new(0) | ||
hxlstatsgroupsgender = hxlstatsmajorgroup.group_by(&:gender) # shorthand for { |hxlstat| hxlstat.gender } | ||
hxlstatsgroupsgender.each do |k_gender, v_gender| | ||
# puts " cycle genders" | ||
# puts " %s " % k_gender | ||
# puts " %s " % v_gender | ||
gender_totals[k_gender] = v_gender.count | ||
end | ||
gender_totals # hash of key gender to v counts | ||
end | ||
|
||
# rubocop:disable MethodLength | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rubocop doesn't need this methodlength exception for this method. Also, you can run rubocop locally without having to wait for CI to build. Just cd into the root of the project and type |
||
def self.get_counts_by_age(hxlstatsmajorgroup) | ||
# Processing Age aggregations | ||
hxlstatsgroupsage = hxlstatsmajorgroup.group_by(&:age) # shorthand for { |hxlstat| hxlstat.age } | ||
# gender *and* age inclusiveness | ||
younger_than_five = 0 | ||
five_twelve_total = 0 | ||
thirteen_eighteen_total = 0 | ||
older_total = 0 | ||
|
||
hxlstatsgroupsage.each do |k_age, _v_age| | ||
# k_age is age, _v_age is array of hxlstatsmatview | ||
# puts " cycle ages" | ||
# puts " %s" % k_age | ||
# puts " %s" % _v_age.count | ||
if k_age < 5 | ||
younger_than_five += 1 | ||
elsif k_age >= 5 && k_age < 13 | ||
five_twelve_total += 1 | ||
elsif k_age >= 13 && k_age <= 18 | ||
thirteen_eighteen_total += 1 | ||
else | ||
older_total += 1 | ||
end | ||
end | ||
[younger_than_five, five_twelve_total, thirteen_eighteen_total, older_total] | ||
end | ||
|
||
# rubocop:disable MethodLength | ||
def self.hxl_stats_counts | ||
results = [] | ||
hxlstats = HxlStatsView.all | ||
|
||
# First group by major categories, before aggregating independently for gender and age and recombining | ||
hxlstatsgroups = hxlstats.group_by { |hxlstat| [hxlstat.mood_rating, hxlstat.stage_of_journey, hxlstat.country] } | ||
hxlstatsgroups.each do |keys, hxlstatsmajorgroup| # keys = mood_rating, stage_of_j, country | ||
gender_totals = get_counts_by_gender(hxlstatsmajorgroup) | ||
younger_than_five, five_twelve_total, thirteen_eighteen_total, older_total = get_counts_by_age(hxlstatsmajorgroup) | ||
results.append([*keys, | ||
hxlstatsmajorgroup.count, | ||
gender_totals[Drawing.genders["female"]], # 1 or 1 | ||
gender_totals[Drawing.genders["male"]], # 0 or 2 | ||
gender_totals[Drawing.genders["other"]] + gender_totals[Drawing.genders["not_specified"]], # 2 or 0 + 3 | ||
five_twelve_total, | ||
thirteen_eighteen_total, | ||
younger_than_five, | ||
older_total]) | ||
end | ||
results | ||
end | ||
|
||
def self.results_by_emotional_state | ||
results = [] | ||
results = results.append(HXLSTATS_COLUMN_HEADERS) | ||
results = results.append(HXL_STATS_TAGS) | ||
results = results.concat(hxl_stats_counts) | ||
results | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<pre> | ||
[ | ||
<% @results.each do | line | %> | ||
<%= line %> | ||
<% end %> | ||
] | ||
</pre> | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,5 +19,7 @@ | |
|
||
resources :drawings, :organisations | ||
|
||
get 'hxlstats', to: 'hxlstats#show' | ||
|
||
root 'drawings#index' | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
class CreateHxlStatsView < ActiveRecord::Migration | ||
def up | ||
execute <<-SQL | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Run locally, some rubocop bits:
|
||
CREATE VIEW hxl_stats_view AS | ||
SELECT d.id AS drawing_id, | ||
d.*, | ||
u.country as user_country, | ||
o.id AS org_id, | ||
o.name AS org_name | ||
FROM drawings d, | ||
users u, | ||
organisations o | ||
WHERE d.user_id = u.id AND | ||
u.organisation_id = o.id | ||
SQL | ||
end | ||
|
||
def down | ||
execute <<-SQL | ||
DROP VIEW IF EXISTS hxl_stats_view | ||
SQL | ||
end | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
require 'rails_helper' | ||
|
||
RSpec.describe HxlstatsController, type: :controller do | ||
describe "GET #show" do | ||
it "returns http success" do | ||
get :show | ||
expect(response).to have_http_status(:success) | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah the 'private class method' debacle! Yeah, wish this was a bit less painful in Rails.
We can use the
private_class_method
option, however this needs to be declared after the methods themselves or Rails complains. A second, think less PITA option, is to use:class << self
around all of the methods. It's usually clearer to use thedef self.method_name
style to define class methods, however when all of the methods within a class are public, wrapping everything inclass << self
is fine and more readable. Also, this way you can use theprivate
keyword as normal.I.e.