2

Railsアプリケーションを作成しようとしていますが、現在、生年月日の表示は通常の日付形式のように表示されますが、代わりに年齢をビューに表示したいと思います。

私がコントローラーで使用している方法は次のとおりです。データベースに生年月日用の列DObがありますL

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歳未満かどうかをチェックするバリデーターを配置するにはどうすればよいですか?

4

6 に答える 6

7

バリデーターには、カスタムメソッドを使用できます。

validate :over_18

def over_18
  if dob + 18.years >= Date.today
    errors.add(:dob, "can't be under 18")
  end
end
于 2012-05-05T16:00:31.337 に答える
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
于 2015-08-05T20:51:31.477 に答える
2

年齢を計算するときは注意が必要です。正しい方法は次のとおりです。

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
于 2012-05-05T16:17:10.687 に答える
1

ここにいくつかの異なる質問があります。

  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
    
  2. その人が18歳以上であることをどのように検証しますか?

    18歳未満の人がデータベースに保存されるのを本当に制限していますか?それとも、視聴能力を制限していますか?

    def is_over_18?
        age >= 18
    end
    

そして、これはカスタムの各バリデーターを書くか、Procを使用しますが、私はこの方法で検証するという決定に本当に疑問を持っています。

于 2012-05-05T16:05:16.060 に答える
1

年齢を見つけるには、gemadroit-ageを使用できます

age = AdroitAge.find_age("23/01/1990")
=> 23
于 2013-09-07T05:21:37.397 に答える
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日やうるう年などを処理します。

于 2012-11-02T13:57:06.897 に答える