2009-02-28 25 views
82

Modelimde Ruby on Rails'teki bir tarihi doğrulamak istiyorum, ancak gün, ay ve yıl değerleri modelime ulaştıklarında yanlış bir tarihe dönüştürülüyor.Bir tarihi raylarda nasıl doğrularım?

Örneğin, 31 Şubat 2009'a görünümümde girersem, denetleyicimde Model.new(params[:model]) kullandığımda, modelimi geçerli bir tarih olarak gördüğü "3 Mart 2009" a çevirir. bu yanlış.

Modelimde bu doğrulamayı yapabilmek istiyorum. Yapabileceğim herhangi bir yol var mı, yoksa tamamen yanlış mı gidiyorum?

"Date validation" numaralı sorunu buldum, ancak bu sorun giderildi. Eğer Modelinizdeki bir tarihe dönüştürülmüş önce tarih dizesi işlemek için gerektiğinden

+1

Bu soruya İçinde

şu anda biridir Rails tarih doğrulaması için en iyi Google sonuçları. Yaptığım gibi ilk geçişte kaçırabilirsin: Seçilen cevabın önemli kısmı validates_timeliness gem. Cevabın geri kalanını bile okumadım çünkü validates_timeliness hakkında başka bir şey öğrendim ve bu taş benim ihtiyaç duyduğum her şeyi özel bir kod yazmak zorunda kalmadan yapıyor. –

cevap

55

Bu tarih için etiket oluşturmak üzere date_select yardımcısını kullandığınızı tahmin ediyorum. Bunu yapmanın başka bir yolu, gün, ay, yıl alanları için seçim formu yardımcısı kullanmaktır. Bu (kullandığım örnek created_at tarih alanıdır) gibisin: bir eklenti çözümü arıyorsanız ben ediyorum,

attr_accessor :month, :day, :year 
validate :validate_created_at 

private 

def convert_created_at 
    begin 
    self.created_at = Date.civil(self.year.to_i, self.month.to_i, self.day.to_i) 
    rescue ArgumentError 
    false 
    end 
end 

def validate_created_at 
    errors.add("Created at date", "is invalid.") unless convert_created_at 
end 

:

<%= f.select :month, (1..12).to_a, selected: @user.created_at.month %> 
<%= f.select :day, (1..31).to_a, selected: @user.created_at.day %> 
<%= f.select :year, ((Time.now.year - 20)..Time.now.year).to_a, selected: @user.created_at.year %> 

Ve modelinde

, tarih doğrulamak validates_timeliness eklentisini kontrol edin. O (github sayfasından) şu şekilde çalışır:

validates_date  - validate value as date 
validates_time  - validate value as time only i.e. '12:20pm' 
validates_datetime - validate value as a full date and time 
validates   - use the :timeliness key and set the type in the hash. 
+0

Önerilen çözüm benim için çalışmıyor ve Rails 2.3.5 kullanıyorum – Roger

+0

Temizleyici olarak yeniden yazdım ve Rails 2.3.5'e karşı test ettim ve bu benim için çalışıyor. –

+0

Merhaba Jack, çözümünüzü denedim, attr_accessible eklemek için çalışıyor: day,: month,: year. Benim için mantıklı değil ... Herhangi bir fikrin varsa teşekkürler! – benoitr

2

, ben senin tarih alanı published_date olduğunu varsayalım o alanın

için erişimci geçersiz olur. modeliniz nesnesine ekleyin:

def published_date=(value) 
    # do sanity checking here 
    # then hand it back to rails to convert and store 
    self.write_attribute(:published_date, value) 
end 
+0

Bunu bu amaçla kullanıp kullanamayacağımı bilmiyorum, ama bu harika bir öneri. –

-3

Eğer validates_date_time eklentiyi denediniz mi?

+0

Bu bağlantı soruyu yanıtlayabilirken, cevabın temel kısımlarını buraya dahil etmek ve referans için bağlantı sağlamak daha iyidir. Bağlantılı sayfa değiştiğinde yalnızca bağlantı yanıtları geçersiz olabilir. – Pinal

+0

Cevabımı daha iyi seviyorum. İki kişi aynı fikirdedir. –

+3

@Pinal Bağlantı şu anda gerçekten ölü. –

19

kronik mücevher kullanma:: İsterseniz

class MyModel < ActiveRecord::Base 
    validate :valid_date? 

    def valid_date? 
    unless Chronic.parse(from_date) 
     errors.add(:from_date, "is missing or invalid") 
    end 
    end 

end 
+2

Bu özel örnekte, string değer girişini elde etmek için 'Chronic.parse (from_date_before_type_cast)' kullanmam gerekiyordu. Aksi halde Rails, alan bir "datetime" alanı olduğundan, dizgiyi "to_date" ile tahmin eder. – Calvin

17

aşağıdaki şekilde kullanılabilir doğrulama yöntemlerinden

class Person < ActiveRecord::Base 
    validates_date :date_of_birth, on_or_before: lambda { Date.current } 
    # or 
    validates :date_of_birth, timeliness: { on_or_before: lambda { Date.current }, type: :date } 
end 

liste vardır Rails 3 veya Ruby 1.9 uyumluluğu, date_validator gem'i deneyin.

+0

Sadece bunu denedim. Doğrulamayı yüklemek ve eklemek için 2 dakikanın hepsini aldınız! – jflores

9

Active Record, yazımdan önce raw özellik verilerini içeren _before_type_cast özniteliklerini verir. Bu, hata mesajlarını önceden yazılan değerlerle döndürmek veya yalnızca yazımdan sonra mümkün olmayan doğrulama yapmak için yararlı olabilir.

Daniel Von Fange'ın erişimciyi geçersiz kılma önerisinden utanırdım, çünkü bir erişim sağlayıcıda doğrulama yapmak erişim sözleşmesini biraz değiştirir. Aktif Kayıt, bu durum için açıkça bir özelliğe sahiptir. Kullan.

1

Burada (eğer özel seçer kullanıyorsanız, params erişimi olan denetleyici bir yerde bir yöntemde)

class Pimping < ActiveRecord::Base 

validate :valid_date? 

def valid_date? 
    if scheduled_on.present? 
    unless scheduled_on.is_a?(Time) 
     errors.add(:scheduled_on, "Is an invalid date.") 
    end 
    end 
end 
+1

Bu her zaman false değerini döndürür: '" 1/1/2013 ".is_a? (Tarih)' - Tarih, kullanıcı girdisinden gelir, böylece bir dize olarak beslenir. İlk randevusu olarak onu ayrıştırmak zorunda mıyım? – Mohamad

+0

Doğru. Date.parse ("1/1/2013"). Is_a? (Tarih) ', ama eğer hiç ayrılmamışsa, muhtemelen bir tarih değildir. – Trip

+1

Argüman hatasını kurtarmanız gerekiyor ... ahh, sadece dizeyi otomatik olarak çözümlemiş olsaydı harika olurdu ... ah, bunun için mücevher var. – Mohamad

0

Sen şöyle tarih ve saati doğrulamak .. olmayan bir kronik bir cevap .. .

# Set parameters 
year = params[:date][:year].to_i 
month = params[:date][:month].to_i 
mday = params[:date][:mday].to_i 
hour = params[:date][:hour].to_i 
minute = params[:date][:minute].to_i 

# Validate date, time and hour 
valid_date = Date.valid_date? year, month, mday 
valid_hour = (0..23).to_a.include? hour 
valid_minute = (0..59).to_a.include? minute 
valid_time = valid_hour && valid_minute 

# Check if parameters are valid and generate appropriate date 
if valid_date && valid_time 
    second = 0 
    offset = '0' 
    DateTime.civil(year, month, mday, hour, minute, second, offset) 
else 
    # Some fallback if you want like ... 
    DateTime.current.utc 
end 
0

saatte burada Biraz ama teşekkürler "How do I validate a date in rails?" Bu doğrulayıcı yazmayı başardı için, umut Birine yararlıdır: senin model.rb

validate :date_field_must_be_a_date_or_blank 

# If your field is called :date_field, use :date_field_before_type_cast 
def date_field_must_be_a_date_or_blank 
    date_field_before_type_cast.to_date 
rescue ArgumentError 
    errors.add(:birthday, :invalid) 
end 
İlgili konular