我想创建显示已注册用户年龄组的统计信息。
示例:
18-24 - 150 registered users
25-34 - 3948 registered users
35-44 - 10028 registered users
45+ - 538 registered users
我在Users表中有一个生日(dob)属性。我从用户模型中计算出他们的年龄:
def age
now = Time.now.utc.to_date
now.year - birthday.year - ((now.month > birthday.month || (now.month == birthday.month && now.day >= birthday.day)) ? 0 : 1)
end
我能做的最好的事情就是:
User.group(:birthday).count
输出每个出生日期的总用户数(不是年龄)。
我希望在视图中输出多年的组。有人可以帮我吗?或者替代方案可以列出每个年龄段的总用户数。无论哪个是最佳解决方案。
答案 0 :(得分:2)
你可以在MySQL中做这样的事情来获得所有8-10岁人的总和:
SELECT COUNT(*) as FROM users WHERE Year(dob) BETWEEN 2004 AND 2006;
或在Rails中
User.where('Year(dob) IN (?)',(2004..2006)).count
使用此代码,您可以执行以下操作以获取年龄组中的人数:
groups = [[18,24],[25,35],[34,44],[45,99]]
current_year = DateTime.now.year
groups.each do |age_group|
range = Range.new(*age_group.map{|y| current_year - y}.reverse)
print age_group.join(" - ")+": "
puts User.where('Year(dob) IN (?)',range).count
end
答案 1 :(得分:2)
创建用于计算用户年龄的实例方法app/models/user.rb
:
def age
now = Time.now.utc.to_date
now.year - birthdate.year - ((now.month > birthdate.month || (now.month == birthdate.month && now.day >= birthdate.day)) ? 0 : 1)
end
创建表示年龄组的对象(我将使用无表格模型,但它可以是纯ruby对象甚至是struct)app/models/age_group.rb
:
class AgeGroup
include ActiveModel::Model # not really necessary, but will add some AM functionality which could be nice later
attr_accessor :from, :to, :count
end
为计算年龄组创建服务对象(选择服务对象只是我个人的偏好。您可以创建一个帮助者或任何您认为最符合您需求的东西)。 app/services/age_groups_service.rb
:
class AgeGroupService
# @params
# ranges - an array of age group ranges. E.g.: [[0, 18], [19, 24], [25, 34], ...]
# users - an array of users from which the age groups will be computed. Defaults to all users
def initialize(ranges = [], users = User.all.to_a)
@ranges = ranges
@users = users
@age_groups = []
end
# Count users in each age group range
# @return
# an array of age groups. E.g.: [{ from: 0, to: 18, count: 12 }, ...]
def call
@ranges.each do |range|
users = @users.select { |user| user.age >= range[0] && user.age <= range[1] }
@age_groups << AgeGroup.new(from: range[0], to: range[1], count: users.length)
end
@age_groups
end
end
将通过调用AgeGroupsService
返回的值分配给控制器中的实例变量:
age_group_service = AgeGroupsService.new([[18, 24], [25, 34], [35, 44], [45, 100]])
@age_groups = age_group_service.call
在视图中打印结果:
<ul>
<% @age_groups.each do |age_group| %>
<li><%= age_group.from %> - <%= age_group.to %>: <b><%= age_group.count %></b></li>
<% end %>
</ul>
一些进一步的想法/说明:
AgeGroup
模型和AgeGroupsService
是不必要的。您可以使用PORO和帮助程序,或者甚至可以将所有代码放入User
模型和相关控制器中。无论如何,我强烈建议不要这样做,因为它会变得混乱而且感觉不对。年龄组似乎值得拥有它自己的位置。