Ruby on rails Ruby中的年龄计算
我正在尝试编写一个rails应用程序,但目前显示出生日期的方式与正常的日期格式类似,但我更喜欢在视图中显示年龄 我在控制器中的方法如下所示,我的数据库中有一列DOb作为出生日期Ruby on rails Ruby中的年龄计算,ruby-on-rails,ruby,datetime,Ruby On Rails,Ruby,Datetime,我正在尝试编写一个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 它显示的像是DO
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岁?对于验证器,您可以使用:
这里有几个不同的问题
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
def is_over_18?
age >= 18
end
这就为每个验证器编写了一个自定义代码,或者使用了一个Proc,但我真的怀疑用这种方式进行验证的决定。在计算年龄时,你应该小心。这里有一个正确的方法:
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
validate:check_over_18
def检查超过18
错误。如果年龄小于18岁,则添加(:dob,“不能低于18”)
结束
我也不得不处理这件事,但已经处理了好几个月了。变得太复杂了。我能想到的最简单的方法是:
def month_number(today = Date.today)
n = 0
while (dob >> n+1) <= today
n += 1
end
n
end
def月号(今天=日期。今天)
n=0
而(dob>>n+1)>n+12)要查找年龄,您可以使用gem
我遇到了这个问题,我想我应该发布一个更现代的答案,利用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
还有规格!
我不明白年龄的问题;张贴你观点的相关代码以澄清。不精确到当天<代码>((日期。新(2000年)。到时间-日期。新(1982年)。到时间)/1.5年)。楼层=>17
@Marc AndréLafortune我想这与闰年有关吧?还是别的什么?@Marc AndréLafortune更新了我的答案。谢谢你指出这一点。我想的更多的是这个方法属于哪里,而不是这个方法本身。这应该是一个更彻底的答案。我认为应该是
,否则18岁的生日就不算了。时间。当前。截止日期
至日期。今天
更好。日期。如果你碰巧将应用程序的时区设置为系统时间以外的某个时间,今天
将无法正常工作。见本讨论:
def age(today = Date.today)
n = 0
while (dob >> n+12) <= today
n += 1
end
n
end
age = AdroitAge.find_age("23/01/1990")
=> 23
# 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
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