मैं रेल में तारीख कैसे मान्य करूँ?


92

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

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

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

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


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

जवाबों:


61

मैं अनुमान लगा रहा हूं कि आप date_selectदिनांक के लिए टैग बनाने के लिए सहायक का उपयोग कर रहे हैं । एक और तरीका है कि आप दिन, महीने, साल के खेतों के लिए चुनिंदा फॉर्म हेल्पर का उपयोग कर सकते हैं। इस तरह (उदाहरण मैंने उपयोग किया है create_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 प्लगइन की जांच करूँगा । यह इस तरह काम करता है (जीथूब पेज से):

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 

उपलब्ध सत्यापन विधियों की सूची इस प्रकार है:

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.

सुझाए गए समाधान मेरे लिए काम नहीं करते हैं और मैं रेल्स 2.3.5 का उपयोग कर रहा हूं
रोजर

मैंने इसे साफ करने के लिए फिर से लिखा, और इसे रेल 2.3.5 के खिलाफ परीक्षण किया और यह मेरे लिए काम करता है।
जैक चू

हाय जैक, मैंने आपके समाधान की कोशिश की है, यह मेरे लिए काम करता है Attr_accessible: day,: month,: year। जो मेरे लिए कोई मतलब नहीं है ... धन्यवाद अगर आपके पास कोई विचार है!
बेनोइटर

रेल 3 में, मैं github.com/adzap/validates_timeliness का उपयोग कर रहा हूं और यह बहुत बढ़िया है।
जेसन स्विट

Validates_timeliness प्लगइन / मणि वास्तव में उपयोग करने के लिए अच्छा है। एक आकर्षण काम करता है और मेरे कोड को छोटा रखता है। पारितोषिक के लिए धन्यवाद।
mjnissim

20

जीर्ण रत्न का उपयोग करना:

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

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

18

यदि आप रेल 3 या रूबी 1.9 संगतता चाहते हैं, तो date_validator मणि का प्रयास करें ।


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

11

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

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


4

चूँकि आपको अपने मॉडल में दिनांक में परिवर्तित होने से पहले दिनांक स्ट्रिंग को संभालना होगा, इसलिए मैं उस क्षेत्र के लिए एक्सेसर को ओवरराइड करूंगा

मान लीजिए कि आपका दिनांक फ़ील्ड है 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

मुझे नहीं पता कि मैं इस उद्देश्य के लिए इसका उपयोग करूंगा, लेकिन यह एक बढ़िया सुझाव है।
डैन रोसेनस्टार्क

3

यहां थोड़ी देर हो गई, लेकिन धन्यवाद " मैं रेल में एक तारीख को कैसे मान्य करूं?" "मैं " मैं इस सत्यापनकर्ता को लिखने में कामयाब रहा, आशा है कि यह किसी के लिए उपयोगी है:

अपने अंदर 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

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?(Date)- यह तिथि उपयोगकर्ता इनपुट से आती है, इसलिए इसे स्ट्रिंग के रूप में खिलाया जा रहा है। मुझे इसे पहले तारीख के रूप में पार्स करना होगा?
मोहम्मद

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

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

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

-3

क्या आपने validates_date_timeप्लग-इन की कोशिश की है?


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

मुझे अपना उत्तर बेहतर लगता है। दो लोग सहमत हैं।
रयान डफल्ड

4
@ मीनल लिंक वास्तव में अब मर चुका है।
वेन कॉनराड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.