Group people by age instead of birth year in stats
When calculating the stats on, say, January 1st 2024, and using a group age of, say, between 20 and 24 years, we were considering that everyone born between 2000 and 2004 had between 20 and 24 years. This wasn't accurate, since most people born in 2004 would have 19 years at that point, and most people born in 1999 would have 24 years.
This commit is contained in:
@@ -120,7 +120,10 @@ class User < ApplicationRecord
|
|||||||
where("username ILIKE ? OR email ILIKE ? OR document_number ILIKE ?", search, search, search)
|
where("username ILIKE ? OR email ILIKE ? OR document_number ILIKE ?", search, search, search)
|
||||||
end
|
end
|
||||||
scope :between_ages, ->(from, to, at_time: Time.current) do
|
scope :between_ages, ->(from, to, at_time: Time.current) do
|
||||||
where(date_of_birth: (at_time - to.years).beginning_of_year..(at_time - from.years).end_of_year)
|
start_date = at_time - (to + 1).years + 1.day
|
||||||
|
end_date = at_time - from.years
|
||||||
|
|
||||||
|
where(date_of_birth: start_date.beginning_of_day..end_date.end_of_day)
|
||||||
end
|
end
|
||||||
|
|
||||||
before_validation :clean_document_number
|
before_validation :clean_document_number
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ describe Budget::Stats do
|
|||||||
describe "#participants_by_age" do
|
describe "#participants_by_age" do
|
||||||
it "returns the age groups hash" do
|
it "returns the age groups hash" do
|
||||||
[21, 22, 23, 23, 34, 42, 43, 44, 50, 51].each do |age|
|
[21, 22, 23, 23, 34, 42, 43, 44, 50, 51].each do |age|
|
||||||
create(:user, date_of_birth: budget.phases.balloting.ends_at - age.years)
|
create(:user, date_of_birth: budget.phases.balloting.ends_at - age.years - rand(0..11).months)
|
||||||
end
|
end
|
||||||
|
|
||||||
allow(stats).to receive(:participants).and_return(User.all)
|
allow(stats).to receive(:participants).and_return(User.all)
|
||||||
@@ -182,7 +182,7 @@ describe Budget::Stats do
|
|||||||
budget = travel_to(50.years.ago) { create(:budget, :finished) }
|
budget = travel_to(50.years.ago) { create(:budget, :finished) }
|
||||||
|
|
||||||
[21, 22, 23, 23, 34, 42, 43, 44, 50, 51].each do |age|
|
[21, 22, 23, 23, 34, 42, 43, 44, 50, 51].each do |age|
|
||||||
create(:user, date_of_birth: budget.phases.balloting.ends_at - age.years)
|
create(:user, date_of_birth: budget.phases.balloting.ends_at - age.years - rand(0..11).months)
|
||||||
end
|
end
|
||||||
|
|
||||||
stats = Budget::Stats.new(budget)
|
stats = Budget::Stats.new(budget)
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ describe Poll::Stats do
|
|||||||
it "returns stats based on what happened when the voting took place" do
|
it "returns stats based on what happened when the voting took place" do
|
||||||
travel_to(100.years.ago) do
|
travel_to(100.years.ago) do
|
||||||
[16, 18, 32, 32, 33, 34, 64, 65, 71, 73, 90, 99, 105].each do |age|
|
[16, 18, 32, 32, 33, 34, 64, 65, 71, 73, 90, 99, 105].each do |age|
|
||||||
create(:user, date_of_birth: age.years.ago)
|
create(:user, date_of_birth: age.years.ago - rand(0..11).months)
|
||||||
end
|
end
|
||||||
|
|
||||||
create(:poll, starts_at: 1.minute.from_now, ends_at: 2.minutes.from_now)
|
create(:poll, starts_at: 1.minute.from_now, ends_at: 2.minutes.from_now)
|
||||||
|
|||||||
@@ -438,6 +438,80 @@ describe User do
|
|||||||
expect(User.between_ages(51, 100).count).to eq 1
|
expect(User.between_ages(51, 100).count).to eq 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "does not consider that people born in the same year share the same age" do
|
||||||
|
april_1st_user = create(:user, date_of_birth: Time.zone.local(2001, 4, 1))
|
||||||
|
april_2nd_user = create(:user, date_of_birth: Time.zone.local(2001, 4, 2))
|
||||||
|
april_3rd_user = create(:user, date_of_birth: Time.zone.local(2001, 4, 3))
|
||||||
|
|
||||||
|
travel_to "2021-04-02" do
|
||||||
|
expect(User.between_ages(18, 19)).to eq [april_3rd_user]
|
||||||
|
expect(User.between_ages(20, 21)).to match_array [april_1st_user, april_2nd_user]
|
||||||
|
expect(User.between_ages(19, 20)).to match_array [april_1st_user, april_2nd_user, april_3rd_user]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "works on leap years with users born on leap years" do
|
||||||
|
leap_day_user = create(:user, date_of_birth: Time.zone.local(2000, 2, 29))
|
||||||
|
march_1st_user = create(:user, date_of_birth: Time.zone.local(2000, 3, 1))
|
||||||
|
|
||||||
|
travel_to "2024-02-28" do
|
||||||
|
expect(User.between_ages(22, 23)).to match_array [leap_day_user, march_1st_user]
|
||||||
|
expect(User.between_ages(23, 24)).to match_array [leap_day_user, march_1st_user]
|
||||||
|
expect(User.between_ages(24, 25)).to eq []
|
||||||
|
end
|
||||||
|
|
||||||
|
travel_to "2024-02-29" do
|
||||||
|
expect(User.between_ages(22, 23)).to eq [march_1st_user]
|
||||||
|
expect(User.between_ages(23, 24)).to eq [leap_day_user, march_1st_user]
|
||||||
|
expect(User.between_ages(24, 25)).to eq [leap_day_user]
|
||||||
|
end
|
||||||
|
|
||||||
|
travel_to "2024-03-01" do
|
||||||
|
expect(User.between_ages(22, 23)).to eq []
|
||||||
|
expect(User.between_ages(23, 24)).to match_array [leap_day_user, march_1st_user]
|
||||||
|
expect(User.between_ages(24, 25)).to match_array [leap_day_user, march_1st_user]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "works on non-leap years with users born on leap years" do
|
||||||
|
leap_day_user = create(:user, date_of_birth: Time.zone.local(2000, 2, 29))
|
||||||
|
march_1st_user = create(:user, date_of_birth: Time.zone.local(2000, 3, 1))
|
||||||
|
|
||||||
|
travel_to "2023-02-28" do
|
||||||
|
expect(User.between_ages(21, 22)).to match_array [leap_day_user, march_1st_user]
|
||||||
|
expect(User.between_ages(22, 23)).to match_array [leap_day_user, march_1st_user]
|
||||||
|
expect(User.between_ages(23, 24)).to eq []
|
||||||
|
end
|
||||||
|
|
||||||
|
travel_to "2023-03-01" do
|
||||||
|
expect(User.between_ages(21, 22)).to eq []
|
||||||
|
expect(User.between_ages(22, 23)).to match_array [leap_day_user, march_1st_user]
|
||||||
|
expect(User.between_ages(23, 24)).to match_array [leap_day_user, march_1st_user]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "works on leap years with users born on non-leap years" do
|
||||||
|
march_1st_user = create(:user, date_of_birth: Time.zone.local(2001, 3, 1))
|
||||||
|
|
||||||
|
travel_to "2024-02-28" do
|
||||||
|
expect(User.between_ages(21, 22)).to eq [march_1st_user]
|
||||||
|
expect(User.between_ages(22, 23)).to eq [march_1st_user]
|
||||||
|
expect(User.between_ages(23, 24)).to eq []
|
||||||
|
end
|
||||||
|
|
||||||
|
travel_to "2024-02-29" do
|
||||||
|
expect(User.between_ages(21, 22)).to eq [march_1st_user]
|
||||||
|
expect(User.between_ages(22, 23)).to eq [march_1st_user]
|
||||||
|
expect(User.between_ages(23, 24)).to eq []
|
||||||
|
end
|
||||||
|
|
||||||
|
travel_to "2024-03-01" do
|
||||||
|
expect(User.between_ages(21, 22)).to eq []
|
||||||
|
expect(User.between_ages(22, 23)).to match_array [march_1st_user]
|
||||||
|
expect(User.between_ages(23, 24)).to match_array [march_1st_user]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "returns users between certain ages on a reference date" do
|
it "returns users between certain ages on a reference date" do
|
||||||
reference_date = 20.years.ago
|
reference_date = 20.years.ago
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user