0

I have this function in my User model that calculates the User ages

def get_age
    now = Time.now.utc.to_date
    now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
end

I want a rails statement that yields a query against the users using this function and returns their age numbers. Then the ages are grouped in labels such as [below 10, between 10-20, etc]

something like:

<%= pie_chart User.group("get_age"), {library: {title: "User's Age"}} %>

where get_age is the function written in users model. Note: even when I define the function as self.get_age still it is not working

ben
  • 6,000
  • 5
  • 35
  • 42
  • So there are a couple of approaches here. One is to do this in the database, in which case we need to know what database you're using. The other is to do it in memory, using Ruby, which will work for a small number of users but will slow down and eventually break for larger numbers of users. Approximately how many User records should this app support? – Peter Goldstein Nov 05 '13 at 20:07
  • am using psql DB, and the app should support lets say thousands of users – ben Nov 05 '13 at 20:11

1 Answers1

1

So for thousands of users I'd definitely do this in the database. While the labels will probably need some massaging, you can start with a query like this:

User.group("date_trunc('year', age(dob))").count

This will result in a hash with entries that look something like this:

{
   "00:00:00" => 3,
   "1 year" => 5,
   "2 years" => 8,
   ...
}

You can then do relabelling and group the year results into bins (e.g. 10-20) as needed. I wouldn't try to do this all in one line in your view - I'd make this a method either on the model or on a dedicated query object.

Peter Goldstein
  • 4,479
  • 2
  • 19
  • 17
  • and would it be simpler to query data from db within a certain range for example: (10..20). How practically can i embed this in the above statement? – ben Nov 05 '13 at 20:44
  • You can, but I don't think it would be simpler. You'd probably want to write a stored function in your database to handle the mapping and relabelling, which you could then invoke from your group method. Trying to squeeze complex logic directly into the argument of a group method seems like a bad idea. – Peter Goldstein Nov 05 '13 at 20:47
  • Which function? The one in the database? Or the one that maps the result in Ruby. As I said above, I think it's simpler to do the latter. – Peter Goldstein Nov 06 '13 at 21:39
  • I have been trying to write the function but I have not succeeded yet. Can you tell me of a way which I edit this User.group("date_trunc('year', age(dob))").count to instead return return an Hash of the ranges??. Like User.group("date_trunc('btn 10-20', age(dob)=>(10..20))").count – ben Nov 06 '13 at 21:47
  • You will forgive me, I am but a starter in rails. I have tried following up this http://stackoverflow.com/questions/12097844/group-users-by-age-range-in-ruby but unfortunately I don't understand – ben Nov 06 '13 at 21:50
  • Database or Ruby? That's what I asked above. Former is hard, latter is relatively easy. – Peter Goldstein Nov 06 '13 at 21:50
  • @ben The question to which you've linked has nothing to do with the problem you're trying to solve. In the question's case the age is precomputed and is an attribute on the model. In your case it isn't. Totally different problem. – Peter Goldstein Nov 06 '13 at 21:57
  • lets do it with the latter easier method – ben Nov 06 '13 at 22:06
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/40672/discussion-between-ben-and-peter-goldstein) – ben Nov 06 '13 at 22:07