I'm trying to write a rails application but presently the display for the date of birth is shown like the normal date format, but I wouldl love to show in views the age instead
The method I have in controller is below and I have a column DOb in my database for date of birthL
def age
@user = user
now = Time.now.utc.to_date
now.year - @user.dob.year - (@user.dob.to_date.change(:year => now.year) > now ? 1 : 0)
end
It shows like DOB: 23/5/2011, but I would like it to be age in years instead.
How do I also put a validator that checks if age is below 18 years?
For the validator, you can use a custom method:
validate :over_18
def over_18
if dob + 18.years >= Date.today
errors.add(:dob, "can't be under 18")
end
end
I ran across this question and thought I'd post a more modern answer that takes advantage of Rails convenience method syntax and custom validators.
This validator will take an options hash for the field name you'd like to validate and the minimum age requirement.
# Include somewhere such as the top of user.rb to make sure it gets loaded by Rails.
class AgeValidator < ActiveModel::Validator
def initialize(options)
super
@field = options[:field] || :birthday
@min_age = options[:min_age] || 18
@allow_nil = options[:allow_nil] || false
end
def validate(record)
date = record.send(@field)
return if date.nil? || @allow_nil
unless date <= @min_age.years.ago.to_date
record.errors[@field] << "must be over #{@min_age} years ago."
end
end
end
class User < ActiveRecord::Base
validates_with AgeValidator, { min_age: 18, field: :dob }
end
User#age convenience methodAnd to calculate the user's age for display, you'll want to be careful to calculate around leap years.
class User < ActiveRecord::Base
def age
return nil unless dob.present?
# We use Time.current because each user might be viewing from a
# different location hours before or after their birthday.
today = Time.current.to_date
# If we haven't gotten to their birthday yet this year.
# We use this method of calculation to catch leapyear issues as
# Ruby's Date class is aware of valid dates.
if today.month < dob.month || (today.month == dob.month && dob.day > today.day)
today.year - dob.year - 1
else
today.year - dob.year
end
end
end
require 'rails_helper'
describe User do
describe :age do
let(:user) { subject.new(dob: 30.years.ago) }
it "has the proper age" do
expect(user.age).to eql(30)
user.birthday += 1.day
expect(user.age).to eql(29)
end
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With