我正在尝试编写一个rails应用程序,但目前显示的出生日期显示为正常的日期格式,但我很乐意在视图中显示年龄而不是
我在控制器中的方法如下,我的数据库中有一个用于出生日期的列DOb
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
它显示像DOB:23/5/2011,但我希望它可以在几年内成为年龄。
如何使用验证器检查年龄是否低于18岁?
答案 0 :(得分:7)
对于验证者,您可以使用custom method:
validate :over_18
def over_18
if dob + 18.years >= Date.today
errors.add(:dob, "can't be under 18")
end
end
答案 1 :(得分:3)
我遇到了这个问题并且认为我发布了一个更现代的答案,它利用了Rails便捷方法语法和自定义验证器。
此验证程序将为您要验证的字段名称和最低年龄要求选择哈希值。
# 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
便捷方法要计算用户的展示年龄,您需要小心计算闰年。
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
答案 2 :(得分:1)
这里有几个不同的问题。
年龄计算属于哪里?
年龄计算应该是辅助方法或模型方法。我总是把它做成一个模型方法,但最近看到了在装饰器甚至辅助方法中使用这些显示元素的优点。在您的情况下,首先将其放入模型,然后从那里开始:
def 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
您如何确认此人已超过18岁?
如果他们未满18岁,你是否真的限制某人被保存到数据库中?或者你是否限制观看能力?
def is_over_18?
age >= 18
end
这会写一个自定义每个验证器或使用Proc,但我真的质疑以这种方式验证的决定。
答案 3 :(得分:1)
计算年龄时应该小心。这是一个正确的方法:
def age(as_at = Time.now)
as_at = as_at.utc.to_date if as_at.respond_to?(:utc)
as_at.year - dob.year - ((as_at.month > dob.month || (as_at.month == dob.month && as_at.day >= dob.day)) ? 0 : 1)
end
之后,根据@Baldrick:
validate :check_over_18
def check_over_18
errors.add(:dob, "can't be under 18") if age < 18
end
答案 4 :(得分:1)
要查找年龄,您可以使用gem adroit-age
age = AdroitAge.find_age("23/01/1990")
=> 23
答案 5 :(得分:0)
我也必须处理这个,但是几个月。变得太复杂了。我能想到的最简单的方法是:
def month_number(today = Date.today)
n = 0
while (dob >> n+1) <= today
n += 1
end
n
end
你可以在12个月内做同样的事情:
def age(today = Date.today)
n = 0
while (dob >> n+12) <= today
n += 1
end
n
end
这将使用Date类来增加月份,这将处理28天和闰年等。