2009-06-26 19 views
27

में एक अवधि फ़ील्ड का उपयोग करके मैं रेल मॉडल में अवधि क्षेत्र का उपयोग करने का सबसे अच्छा तरीका ढूंढ रहा हूं। मैं प्रारूप एचएच होना चाहता हूं: एमएम: एसएस (पूर्व: 01:30:23)। उपयोग में डेटाबेस स्थानीय स्तर पर और उत्पादन में पोस्टग्रेज़ है।रेल मॉडल

मैं भी तो मैं क्षेत्र में वस्तुओं के सभी पर एक नज़र डालें और उस मॉडल में सभी वस्तुओं के कुल समय के साथ आते हैं और की तरह कुछ के साथ खत्म हो सकता है इस क्षेत्र के साथ काम करना चाहते हैं:

30 रिकॉर्ड 45 घंटे, 25 मिनट, और 34 सेकंड कुल रिकॉर्ड।

तो क्या सबसे अच्छा काम करेगा? माइग्रेशन CRUD रूपों के लिए

  • प्रपत्र क्षेत्र के लिए

    • फील्ड प्रकार (घंटा, मिनट, दूसरे ड्रॉप चढ़ाव?)
    • कम से कम महंगा विधि मॉडल में सभी रिकॉर्ड की कुल अवधि उत्पन्न करने के लिए
  • उत्तर

    41
    • अपने डेटाबेस में पूर्णांक के रूप में स्टोर करें (सेकंड की संख्या, शायद)।
    • आपका प्रवेश फॉर्म सटीक उपयोग के मामले पर निर्भर करेगा। ड्रॉपडाउन दर्दनाक हैं; घंटे + मिनट + सेकंड में अवधि के लिए छोटे टेक्स्ट फ़ील्ड का उपयोग करना बेहतर है।
    • कुल मिलाकर कुल मिलाकर SUM क्वेरी अवधि कॉलम पर क्वेरी चलाएं। यदि आप पूर्णांक का उपयोग करते हैं, तो यह आसान और तेज़ है।

    इसके अतिरिक्त:

    • अपने विचारों में अवधि प्रदर्शित करने के लिए एक सहायक का उपयोग करें। 123.seconds (123 को डेटाबेस से पूर्णांक के साथ प्रतिस्थापित करके) को ActiveSupport::Duration पर सेकेंड के पूर्णांक के रूप में आसानी से एक अवधि परिवर्तित कर सकते हैं। अच्छे स्वरूपण के लिए परिणाम Duration पर inspect का उपयोग करें। (यह सही नहीं है। आप स्वयं कुछ लिखना चाह सकते हैं।)
    • अपने मॉडल में, आप संभवत: पाठकों और लेखकों को विशेषता चाहते हैं जो पूर्णांक की बजाय ActiveSupport::Duration ऑब्जेक्ट्स को वापस ले लें/लें। बस duration=(new_duration) और duration को परिभाषित करें, जो आंतरिक रूप से read_attribute/write_attribute पूर्णांक तर्कों के साथ कॉल करता है।
    +0

    +1 मेरे द्वारा कम समय में मेरी टिप्पणी को पोस्ट करने के लिए +1! :) –

    +0

    मैंने सेकंड का उपयोग करने पर कभी विचार नहीं किया, दोह! पारितोषिक के लिए धन्यवाद! – mwilliams

    +0

    आउटपुट प्रारूपित करने के लिए आप 'निरीक्षण' का उपयोग कैसे करते हैं? उदाहरण? –

    5

    मैंने ActiveSupport :: अवधि का उपयोग करने का प्रयास किया लेकिन आउटपुट को स्पष्ट करने में परेशानी थी।

    आप ruby-duration पसंद कर सकते हैं, एक अपरिवर्तनीय प्रकार जो सेकंड में सटीकता के साथ कुछ समय का प्रतिनिधित्व करता है। इसमें बहुत सारे परीक्षण हैं और एक मोंगोइड मॉडल फ़ील्ड प्रकार है।

    मैं मानव अवधि स्ट्रिंग को आसानी से पार्स करना चाहता था इसलिए मैं Chronic Duration के साथ गया। यहां एक मॉडल में जोड़ने का एक उदाहरण दिया गया है जिसमें सेकेंड फ़ील्ड में time_spent है।

    class Completion < ActiveRecord::Base 
        belongs_to :task 
        belongs_to :user 
    
        def time_spent_text 
        ChronicDuration.output time_spent 
        end 
    
        def time_spent_text= text 
        self.time_spent = ChronicDuration.parse text 
        logger.debug "time_spent: '#{self.time_spent_text}' for text '#{text}'" 
        end 
    
    end 
    
    3

    मैं समर्थन और ActiveRecord::Duration के रूप में उपयोग PostgreSQL के interval प्रकार के लिए एक कुछ ठूंठ लिखा गया है।

    इस गीस्ट को देखें (आप इसे रेल 4 में प्रारंभकर्ता के रूप में उपयोग कर सकते हैं।1): https://gist.github.com/Envek/7077bfc36b17233f60ad

    वहाँ रेल के लिए इसके अलावा, मैं खोल दिया है पुल अनुरोध: https://github.com/rails/rails/pull/16919

    +0

    हमने रेल 5.1 के लिए एक अद्यतन गिस्ट लिखा है: https://gist.github.com/vollnhals/a7d2ce1c077ae2289056afdf7bba094a –

    4

    रेल 5 में, आप ActiveRecord :: ISO8601 तारों के रूप में ActiveSupport :: अवधियां स्टोर करने के लिए विशेषताओं का उपयोग कर सकते हैं। पूर्णांक पर ActiveSupport :: अवधि का उपयोग करने का लाभ यह है कि आप उन्हें बॉक्स के ठीक पहले दिनांक/समय गणना के लिए उपयोग कर सकते हैं। आप Time.now + 1.month जैसी चीजें कर सकते हैं और यह हमेशा सही होता है।

    आइए जानें:

    जोड़े config/initializers/duration_type.rb

    class DurationType < ActiveRecord::Type::String 
        def cast(value) 
        return value if value.blank? || value.is_a?(ActiveSupport::Duration) 
    
        ActiveSupport::Duration.parse(value) 
        end 
    
        def serialize(duration) 
        duration ? duration.iso8601 : nil 
        end 
    end 
    
    ActiveRecord::Type.register(:duration, DurationType) 
    

    प्रवासन

    create_table :somethings do |t| 
        t.string :duration 
    end 
    

    मॉडल

    class Something < ApplicationRecord 
        attribute :duration, :duration 
    end 
    

    प्रयोग

    something = Something.new 
    something.duration = 1.year # 1 year 
    something.duration = nil 
    something.duration = "P2M3D" # 2 months, 3 days (ISO8601 string) 
    Time.now + something.duration # calculation is always correct 
    
    संबंधित मुद्दे