5

I have a Rails 3.2.18 app where in my form I have a field for age (int) and date of birth (datetime). I will be using a simple jQuery date picker to select the DOB.

Here's what I want to happen.

The first field is the DOB (Date of birth). I want to select that, and as soon as it's selected I'd like to calculate the age and automatically fill the age field based off of that selection.

I think I can do it somehow by creating a method on the model that calculates the age, but I'm not sure how to populate it in the age field. Perhaps some Javascript or something?

Any help would be greatly appreciated.

Below is a method I wrote for another app that calculates age based on DOB and can be used in a view:

def age(dob)
    now = Time.zone.now.to_date
    now.year - patient_dob.year - ((now.month > patient_dob.month || (now.month == patient_dob.month && now.day >= patient_dob.day)) ? 0 : 1)
  end
nulltek
  • 3,247
  • 9
  • 44
  • 94

2 Answers2

5

What you are suggesting is not possible to do in Ruby. You can use JavaScript.

It's not possible to calculate the age, based on user input, without first traveling to the server, calculating the age, and then rendering the result to the client. The model has no knowledge of the date that the user puts in; this is, unless you submit the form, of course.

It's possible to submit the form via Ajax. For example, some sites let you fill in a zip code, and then they prefil the address for you. What is really happening is, behind the scenes, the browser is sending an ajax request to a server that returns an address.

In your case you shouldn't have to do that since calculating the age in JavaScript is very easy. It's also quicker to do it on the client since it saves you the round trip to the server.

Take a look at this answer which shows you how to calculate a persons age based on an input date.

If you are using Rails you will likely be using jQuery. In which case you can do something like this:

$('#date_input').on('change', function () {
  date = $(this).val();
  age = getAge(date);
  $('#age_input').val(age);
});

# This is taken directly from this answer: https://stackoverflow.com/a/7091965/276959
function getAge(dateString) {
    var today = new Date();
    var birthDate = new Date(dateString);
    var age = today.getFullYear() - birthDate.getFullYear();
    var m = today.getMonth() - birthDate.getMonth();
    if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
        age--;
    }
    return age;
}

Then, on the server you may want to recalculate the age before you save the data into the database. This is because nothing stops the user from submitting a false age directly. Either by filling it in, or by altering the DOM.

class Person
  before_save :set_age

private

  def set_age
    self.age = # Calculate age here.
  end
end

See this answer on how to calculate age using Ruby, which looks identical to the code you have in your question.

Community
  • 1
  • 1
Mohamad
  • 34,731
  • 32
  • 140
  • 219
  • This seems like it would work but the jQuery throws all sorts of errors and crashes the app. – nulltek Jun 05 '14 at 13:16
  • 1
    @teknull It's a bit hard to diagnose the problem without any details, but it's probably because you have some syntax error, or load error in your app. This code stills needs to be setup properly, in the right place, and made to work with Turbolinks if you are using it. But all of that is trivial to get it working. – Mohamad Jun 05 '14 at 14:20
  • This guy gave an answer that was incorrect then copied my answer below Then commented to make it appear my answer has issues typical stack hacks.. booo him – Abs Jun 07 '14 at 09:33
  • 2
    @JetAbe, Mohamad posted the above on May 29th (and nicely gives credit to [another answer](http://stackoverflow.com/questions/4060004/calculate-age-in-javascript/7091965#7091965)), 8 minutes later edited to add a note about server validation, and then [days later on June 4th you came along and posted yours](http://stackoverflow.com/posts/23828931/timeline). Why are you complaining about copying? – Arjan Jun 07 '14 at 11:46
  • @Mohamad I was able to get this to work. It looks like my JS syntax was wrong when I was adding the functionality to my application.js file. Thanks for your help, it's working great! – nulltek Jun 24 '14 at 15:23
0

This is a more client side javascript way to achieve this with date accuracy using server.

In your rails view when parent page loads

<%= javascript_tag do%>
    var currDate = new Date('<%= Date.today%>');
<%end%>

In your js file (i assumed date-picker to be the input selected using date picker.)

function calcAge(dateString) {
    var birthDate = new Date(#('date_picker').val());
    var age = currDate.getFullYear() - birthDate.getFullYear();
    var m = currDate.getMonth() - birthDate.getMonth();
    if (m < 0 || (m === 0 && currDate.getDate() < birthDate.getDate())) {
        age--;
    }
    return age;
}

Then just need to call calcAge on date selected event and the

return age; 

can change to set value on an input field

$('#ageField').val(age);
Abs
  • 3,902
  • 1
  • 31
  • 30
  • He would still need to calculate the age on the sever from the date of birth field. So sending back a server date seems contrived, don't you think? I don't see that it would do any good, other than, in the unlikely event that the user's system date was out of synch by many months. – Mohamad Jun 05 '14 at 12:06
  • Calc age does calculate age for you using JavaScript from a date picker date of birth .. Then it's upto your design requirements what you wanna do with the age – Abs Jun 05 '14 at 12:45
  • Yes, but why bother setting the date on the server? It does no good as far as I can see. User submitted data should never be trusted, hence why the age must be calculated on the server anyway. So sending back a date object is, well, redundant.... – Mohamad Jun 05 '14 at 14:21
  • Its current time which should not be referenced from client machine and has no relation with setting date on server. its not getting sent back but requested – Abs Jun 05 '14 at 15:45
  • 1
    That still doesn't answer the question. Setting the date on the server is redundant. What does it achieve? Having this ugly inline JS `var currDate = new Date('<%= Date.today%>')` is better than a simple `new Date()` in what way? – Mohamad Jun 05 '14 at 15:52
  • http://stackoverflow.com/questions/13889853/how-to-get-the-server-date-in-javascript Do you want users to be able to make themselves any age by changing system time then you go with new Date().... – Abs Jun 05 '14 at 17:27
  • LOL! That's why he has to calculate the age again on the server based on the date, not the age field. And how does setting the JavaScript in that snippet stop someone from opening dev tools and setting the date manually? – Mohamad Jun 05 '14 at 17:40
  • 1
    My point is, you only need the server date on the server, to convert the date string sent in the form to an age. Sending back the server date is pointless, and useless. – Mohamad Jun 05 '14 at 17:41
  • my friend unless i understood the problem incorrectly ... They wanted to compute age on a web form when date is selected from date picker.. The server date is a reference point to use for calculating that age..once it is computed we send that back.. it can even be a readOnly field...in any case with DOB you never need to store age.. – Abs Jun 05 '14 at 17:47
  • 1
    "in any case with DOB you never need to store age" <- Exactly! So why bother setting some JS server side? Calculate the age it in the browser for the users pleasure, maybe on `onBlur`. Then, on the server use the DOB to calculate the age safely. Problem solved. – Mohamad Jun 05 '14 at 17:53
  • Go for it. I think you are misunderstanding something fundamental, yet simple, here. – Mohamad Jun 05 '14 at 18:09
  • Ever heard this Ignorance is a bliss! – Abs Jun 05 '14 at 18:22
  • 1
    As for @Mohamad wondering why starting with `var currDate = new Date('<%= Date.today%>');`: I feel using the server date is even incorrect for this scenario, as from the user's time zone perspective the server's date might be one day ahead or behind. I feel it would be weird to see my age calculated wrongly when I fill in the form on my birthday just as the server lives in a different time zone. – Arjan Jun 07 '14 at 11:59
  • Hello arjan ever heard of geo Ip lookup for location.. I guess not... Ever heard of saving user time zone as part of user info.. Never worked on smart systems have you – Abs Jun 07 '14 at 12:12