我遇到了这个问题,并认为我会发布一个更现代的答案,它利用 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