2009-02-28 31 views
82

मैं रूबी पर रेल में अपने मॉडल में एक तिथि को सत्यापित करना चाहता हूं, हालांकि, दिन, महीने और साल के मूल्य पहले से ही मेरे मॉडल तक पहुंचने तक गलत तिथि में परिवर्तित हो जाते हैं।मैं रेल में दिनांक कैसे सत्यापित करूं?

उदाहरण के लिए, अगर मैं अपने विचार में 31 फरवरी 200 9 में प्रवेश करता हूं, तो जब मैं अपने नियंत्रक में Model.new(params[:model]) का उपयोग करता हूं, तो यह इसे "3 मार्च 200 9" में परिवर्तित करता है, जो मेरा मॉडल तब मान्य दिनांक के रूप में देखता है, लेकिन यह है, लेकिन यह गलत है

मैं अपने मॉडल में यह सत्यापन करने में सक्षम होना चाहता हूं। क्या कोई तरीका है कि मैं कर सकता हूं, या क्या मैं इस बारे में पूरी तरह गलत हूं?

मुझे यह "Date validation" मिला जो समस्या पर चर्चा करता है लेकिन इसे कभी हल नहीं किया गया था।

+1

यह सवाल अंदर

वर्तमान में से एक है रेल की तारीख सत्यापन के लिए शीर्ष Google परिणाम। आप इसे पहले पास पर याद कर सकते हैं जैसे मैंने किया: चयनित उत्तर का महत्वपूर्ण हिस्सा validates_timeliness मणि है। मैंने बाकी जवाब भी नहीं पढ़ा क्योंकि मुझे कहीं और मान्यताओं के बारे में पता चला है, और यह मणि मुझे बिना किसी कस्टम कोड लिखने के लिए जो कुछ भी चाहिए, वह करता है। –

उत्तर

55

मुझे लगता है कि आप तिथि के लिए टैग जेनरेट करने के लिए date_select सहायक का उपयोग कर रहे हैं। एक और तरीका यह है कि आप इसे कर सकते हैं दिन, महीने, साल के क्षेत्रों के लिए चयन फार्म सहायक का उपयोग करना है। जैसा इस (उदाहरण मैं प्रयोग किया जाता created_at दिनांक फ़ील्ड है):

<%= 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 %> 

और मॉडल में, आप तारीख को मान्य:

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 

आप एक प्लगइन समाधान के लिए देख रहे हैं, मैं था चेकआउट validates_timeliness प्लगइन। यह (GitHub पेज से) इस तरह काम करता है:

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

सुझाया गया समाधान मेरे लिए काम नहीं करता है और मैं रेल 2.3.5 – Roger

+0

का उपयोग कर रहा हूं, मैं इसे क्लीनर के रूप में पुनः लिखता हूं, और रेल 2.3.5 के खिलाफ इसका परीक्षण करता हूं और यह मेरे लिए काम करता है। –

+0

हाय जैक, मैंने आपके समाधान की कोशिश की है, यह मेरे लिए attr_accessible जोड़ने का काम करता है: दिन,: महीना, वर्ष। जो मेरे लिए समझ में नहीं आता है ... धन्यवाद अगर आपको कोई विचार है! – benoitr

2

जब से तुम दिनांक स्ट्रिंग को संभालने के लिए इससे पहले कि यह अपने मॉडल में एक तिथि में बदल जाती है की जरूरत है, मुझे लगता है कि क्षेत्र

के लिए एक्सेसर ओवरराइड था मान लें कि आपका दिनांक फ़ील्ड published_date में है। अपने मॉडल वस्तु को यह करें:

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

मुझे नहीं पता कि मैं इस उद्देश्य के लिए इसका उपयोग करूंगा, लेकिन यह एक अच्छा सुझाव है। –

-3

आप validates_date_time प्लग-इन की कोशिश की?

+0

हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन यहां उत्तर के आवश्यक हिस्सों को शामिल करना बेहतर है और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक किए गए पृष्ठ में परिवर्तन होने पर लिंक-केवल उत्तर अमान्य हो सकते हैं। – Pinal

+0

मुझे अपने उत्तर को बेहतर पसंद है। दो लोग सहमत हैं। –

+3

@ पिनिन लिंक वास्तव में अब मर चुका है। –

19

पुरानी मणि का उपयोग करना::

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

इस विशिष्ट उदाहरण में, मुझे स्ट्रिंग मान इनपुट प्राप्त करने के लिए 'Chronic.parse (from_date_before_type_cast)' का उपयोग करना पड़ा। अन्यथा फ़ील्ड 'to_date' के साथ स्ट्रिंग को टाइपकास्ट करेगा क्योंकि फ़ील्ड' डेटाटाइम 'फ़ील्ड था। – Calvin

17

अगर आप चाहते हैं

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 

सत्यापन उपलब्ध विधि की सूची इस प्रकार हैं रेल 3 या रूबी 1.9 संगतता date_validator मणि का प्रयास करें।

+0

मैंने अभी यह कोशिश की। स्थापित करने और सत्यापन जोड़ने के लिए सभी 2 मिनट ले लिया! – jflores

9

सक्रिय रिकॉर्ड आपको _before_type_cast विशेषता देता है जिसमें टाइपकास्टिंग से पहले कच्चे विशेषता डेटा होते हैं। यह प्री-टाइपकास्ट मानों के साथ त्रुटि संदेशों को वापस करने या टाइपकास्ट के बाद संभव नहीं होने वाले सत्यापन करने के लिए उपयोगी हो सकता है।

मैं एक्सेसर को ओवरराइड करने के डैनियल वॉन फेंग के सुझाव से दूर शर्मिंदा हूं, क्योंकि एक एक्सेसर में सत्यापन करने से एक्सेसर अनुबंध थोड़ा बदल जाता है। सक्रिय रिकॉर्ड में इस स्थिति के लिए स्पष्ट रूप से एक सुविधा है। इसका इस्तेमाल करें।

1

यहाँ एक गैर पुरानी जवाब है ..

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

यह हमेशा झूठा देता है: '" 1/1/2013 ".is_a? (दिनांक)' - तिथि उपयोगकर्ता इनपुट से आती है, इसलिए इसे स्ट्रिंग के रूप में खिलाया जा रहा है। मुझे इसे पहले एक तारीख के रूप में पार्स करना होगा? – Mohamad

+0

सही। 'Date.parse (" 1/1/2013 ") is_a? (दिनांक) ', लेकिन आप देख सकते हैं कि अगर यह बिल्कुल विश्लेषण नहीं करता है, तो शायद यह भी एक तारीख नहीं है। – Trip

+1

तर्क त्रुटि को बचाने की आवश्यकता है ... आह, यह शानदार होगा अगर यह स्वचालित रूप से स्ट्रिंग को पार्स कर देता है ... ओह ठीक है, उसके लिए मणि है। – Mohamad

0

आप दिनांक और इतने की तरह समय (एक विधि में कहीं अपने नियंत्रक में पहुंच कर अपने परम करने के लिए यदि आप कस्टम का चयन का उपयोग कर रहे) मान्य कर सकते हैं .. ।

# 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

देर यहाँ थोड़ा है, लेकिन धन्यवाद करने के लिए "How do I validate a date in rails?" मैं इस सत्यापनकर्ता लिखने में कामयाब रहे, आशा किसी के लिए उपयोगी है: अपने 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 
संबंधित मुद्दे