25

मैं पुनरावर्ती घटनाओं को मॉडल करने का सबसे अच्छा तरीका खोज रहा हूं। मैं घटनाओं को प्रदर्शित करने के लिए fullcalendar का उपयोग कर रहा हूँ। लेकिन मुझे लगता है कि आवर्ती घटनाओं को रेल बैकएंड पर सबसे अच्छा संभाला जाता है।कैलेंडर में पुनरावर्ती घटनाक्रम - रेल

मैंने पहले से ही अन्य प्रश्नों और मौजूदा उदाहरण कोड को देखा है, लेकिन मुझे कुछ भी नहीं मिला जो फिट बैठता है।

यह Google कैलेंडर की तरह व्यवहार करना चाहिए। तो यह आवर्ती ईवेंट श्रृंखला के को हटा/संशोधित करना संभव होना चाहिए। लेकिन डेटाबेस में इवेंट श्रृंखला की सभी घटनाओं को सहेजना अक्षम लगता है। बिना किसी पुनरावृत्ति के एकल कार्यक्रम बनाना भी संभव होना चाहिए।

एक अच्छा मॉडल आर्किटेक्चर क्या होगा?

मेरे घटना मॉडल अभी कि तरह लग रहा है (अतिरिक्त गुण बिना ):

# Table name: events 
# 
# id    :integer   not null, primary key 
# employee_id  :integer 
# created_at  :datetime 
# updated_at  :datetime 
# starts_at  :datetime 
# ends_at   :datetime 
# 

class Event < ActiveRecord::Base 
    attr_accessible :starts_at, :ends_at 
end 

उत्तर

37

यहां यह है कि मैं इसे कैसे मॉडल करूंगा। मैंने Google कैलेंडर का अधिक उपयोग नहीं किया है, इसलिए मैं iCal की पुनरावर्ती घटनाओं की कार्यक्षमता का आधार बना रहा हूं।

सभी मॉडलों में सामान्य आईडी, create_at, update_at गुण होना चाहिए। सूचीबद्ध कस्टम गुण हैं। यदि संपत्ति एक और मॉडल है, तो आप इसे has_one या belongs_to जैसे एक सहयोगी लागू करेंगे।

  • RecurrencePeriod
    • Event base_event # has_one :base_event, :class_name'Event'
    • Time end_date #, नहीं के बराबर हो सकता है अगर यह हमेशा के लिए फिर से होता है
    • WeeklyRecurrence पुनरावृत्ति # has_one :recurrence, :as=>:recurrence
    • Array[OccurrenceOverride] ओवरराइड # has_many :overrides, :class_name=>'OccurrenceOverride'

तारीख है कि इसके base_event शुरू होता है पर RecurrencePeriod शुरू होता है। साथ ही, मुझे लगता है कि Event का कर्मचारी_आई उस कर्मचारी को संदर्भित करता है जिसने उस ईवेंट को बनाया है। RecurrencePeriod उस कर्मचारी से भी संबंधित होगा जिसने base_event बनाया है।

मॉडल इस बात पर निर्भर करता है कि आप कितनी लचीली रूप से आवर्ती निर्दिष्ट करने में सक्षम होना चाहते हैं। क्या आप "मंगलवार और गुरुवार को हर दो सप्ताह 10 बजे से 11 बजे तक और दोपहर 2 बजे से शाम 3 बजे तक" या "साप्ताहिक दोहराते हैं" का समर्थन करने जा रहे हैं? यहां एक मॉडल है जो "साप्ताहिक दोहराता है" का समर्थन करता है, "हर दो सप्ताह दोहराता है", आदि; यदि आपको आवश्यकता हो तो आप इसका विस्तार कर सकते हैं।

  • WeeklyRecurrence
    • Integer weeks_between_recurrences
    • RecurrencePeriod RECURRENCE_PERIOD # belongs_to :recurrence, :polymorphic=>true

मैं polymorphic associations यहाँ का उपयोग करें, क्योंकि मुझे लगता है कि वे उपयोगी हो सकता है अगर आप एक से अधिक प्रकार चाहते हैं पुनरावृत्ति की तरह,दोनोंऔर DailyRecurrence। लेकिन मुझे यकीन नहीं है कि वे मॉडल करने का सही तरीका हैं, इसलिए यदि वे बाहर नहीं निकलते हैं, तो बस इसके बजाय has_one :weekly_recurrence और belongs_to :recurrence_period का उपयोग करें।

Ice cube लाइब्रेरी ऐसा लगता है कि यह पुनरावर्तन की गणना के लिए उपयोगी हो सकता है। यदि ऊपर WeeklyRecurrence पर्याप्त शक्तिशाली नहीं है, तो आप WeeklyRecurrence को प्रतिस्थापित करते हुए मॉडल में एक आइस क्यूब Schedule ऑब्जेक्ट स्टोर करना चाहते हैं। मॉडल में Schedule ऑब्जेक्ट को स्टोर करने के लिए, इसे "शेड्यूल" विशेषता के रूप में सहेजें, मॉडल परिभाषा में serialize :schedule डालें, और डेटाबेस में टेक्स्ट कॉलम "शेड्यूल" बनाएं।

OccurrenceOverride एक पुनरावर्ती घटना के संपादन के एक उदाहरण के मामले को संभालता है।

  • OccurrenceOverride
    • RecurrencePeriod recurrence_period_to_override # belongs_to :recurrence_period_to_override, :class_name=>'RecurrencePeriod'
    • Time original_start_time # विशिष्ट पहचान करता है जो पुनरावृत्ति कि RecurrencePeriod भीतर बदलने के लिए
    • Event replacement_event # has_one :replacement_event, :class_name=>'Event'; , नहीं के बराबर हो सकता है अगर है कि पुनरावृत्ति के बजाय नष्ट कर दिया गया संपादित

इसके बजाय व्यक्तिगत रूप से एक घटना के प्रत्येक घटना के भंडारण के लिए, उन्हें अस्थायी रूप से उत्पन्न जब आप उन्हें ध्यान में रखते हुए दिखाने की जरूरत है। RecurrencePeriod में, एक विधि generate_events_in_range(start_date, end_date) बनाएं जो Event एस उत्पन्न करती है, डेटाबेस में सहेजने के लिए नहीं, बल्कि केवल दृश्य को पास करने के लिए ताकि यह उन्हें दिखा सके।

जब कोई उपयोगकर्ता पुनरावृत्ति संपादित करता है, तो उनके पास सभी घटनाओं, सभी भविष्य की घटनाओं, या बस उस घटना को संशोधित करने का विकल्प होना चाहिए। यदि वे सभी घटनाओं को संशोधित करते हैं, तो RecurrencePeriod के base_event को संशोधित करें। यदि वे सभी भविष्य की घटनाओं को संशोधित करते हैं, तो RecurrencePeriod पर लागू होने वाली विधि का उपयोग करें जो स्वयं को किसी निश्चित तिथि के दोनों ओर दो RecurrencePeriod एस में विभाजित करता है, और फिर परिवर्तन को दूसरी अवधि में सहेजता है। यदि वे केवल उस ईवेंट को संशोधित करते हैं, तो वे OccurrenceOverride बनाएं जब वे ओवरराइड कर रहे हों, और ओवरराइड के प्रतिस्थापन_वेंव में परिवर्तनों को सहेजें।

जब कोई उपयोगकर्ता कहता है कि एक निश्चित घटना को अब निकट भविष्य के लिए हर दो सप्ताह में दोहराया जाना चाहिए, तो आपको उस ईवेंट के साथ बेस_एवेंट और एक शून्य end_date के रूप में एक नया RecurrencePeriod बनाना चाहिए। इसका पुनरावृत्ति सप्ताह 0bसप्ताह_between_recurrence = 2 के साथ होना चाहिए, और इसमें OccurrenceOverride एस नहीं होना चाहिए।

+1

किसी भी समस्या को बरकरार रखने के अनुभव से कोई समस्या नहीं है, हालांकि आईडी द्वारा इसे एक्सेस करने में सक्षम नहीं है? (प्रदर्शन, जटिलता, आदि) – ted

+0

@ अच्छा सवाल है। मैंने कभी इसे लागू नहीं किया है, इसलिए मुझे डर है कि मुझे नहीं पता कि क्या उत्पन्न होने वाली घटनाएं किसी भी समस्या का कारण बनती हैं। मुझे लगता है कि अगर आवश्यक हो तो आप उत्पन्न घटनाओं के लिए एक कैश स्थापित कर सकते हैं। एक कैशिंग सिस्टम इस तथ्य का उपयोग कर सकता है कि सहेजने के लिए उत्पन्न उत्पन्न घटना अवधारणात्मक रूप से 'OccurrenceOverride' के समान ही है, हालांकि समान नहीं है। –

3

बस मेरे सिर के ऊपर से एक राय है, शायद comenters बाहर एक समस्या मैं के बारे में सोच नहीं कर रहा हूँ इंगित करेगा फिलहाल:

मैं RecurringEvent मॉडल (या जो भी आप इसे कॉल करना चाहते हैं) has_many :events बनाउंगा।

मान लें कि प्रत्येक ईवेंट किसी कर्मचारी (आपके नोट्स के आधार पर) द्वारा बनाई गई है, तो RecurringEvent भी belong_to :employee होगा। इसके बाद आप has_many :through संबंध बना सकते हैं जहां एक कर्मचारी के पास कई घटनाएं होती हैं और इसमें कई पुनरावर्ती घटनाएं होती हैं।

पुनरावर्ती मॉडल मॉडल की आरंभ तिथि और पैटर्न हो सकता है, और यह प्रारंभिक घटनाओं को बनाने के लिए प्रारंभ में इस पैटर्न का उपयोग कर सकता है। फिर आवर्ती श्रृंखला का हिस्सा होने वाली किसी भी घटना पर आप उस व्यक्तिगत अवसर को संशोधित या हटा सकते हैं, लेकिन आप श्रृंखला में सभी घटनाओं (या श्रृंखला में सभी भविष्य की घटनाओं) को हटाने और उन्हें पुनर्निर्माण के आधार पर 'श्रृंखला को पुन: उत्पन्न कर सकते हैं' एक नया पैटर्न, उदाहरण के लिए मीटिंग को "हर मंगलवार" से "हर गुरुवार" तक ले जाएं।

इस बारे में एक और अच्छी बात यह है कि आप पुनरावर्ती घटनाओं की एक नज़र में एक सूची बना सकते हैं, जो आपको लोगों के प्रमुख दायित्वों में कुछ अच्छी जानकारी दे सकता है।

जैसा कि मैंने कहा, यह है कि मैं इसे कैसे दृष्टिकोण होगा, लेकिन यह सिर्फ एक विचार है और मैं ऐसा कुछ नहीं बनाया गया है तो मैं अगर कोई बड़ा gotchas हैं पता नहीं है मेरे सिर के ऊपर से दृष्टिकोण में मैं सुझाव दे रहा हूँ।

शुभकामनाएं, कृपया जो भी आप कर रहे हैं उसे पोस्ट करें!

5

मेरे मामले में मैं कुछ इस तरह किया:

# Holds most of my event's data; name, description, price ... 
class Event < ActiveRecord::Base 
    has_many :schedules 
    has_many :occurrences 
    attr_accessible :started_at, :expired_at # expired_at is optional 
end 

# Holds my schedule object 
class Schedule < ActiveRecord::Base 
    belongs_to :event 
    attr_accessible :ice_cube_rule # which returns my deserialized ice_cube object 
end 

# Holds generated or manually created event occurrences 
class Occurrence < ActiveRecord::Base 
    belongs_to :event 
    attr_accessible :started_at, :expired_at 
    attr_accessible :generated # helps me tell which occurrences are out of an ice_cube generated serie 
    attr_accessible :canceled_at 
end 

वहाँ से, मैं ice_cube इस्तेमाल किया घटनाओं गणना और संग्रहीत घटनाओं तालिका में परिणाम का प्रबंधन करने के। मैंने पहली बार घटना मॉडल के बिना काम करने की कोशिश की, लेकिन इससे कोई फर्क नहीं पड़ता कि नियम इंजन कितना उन्नत है, आपके पास हमेशा अपवाद होंगे, इसलिए अपने मॉडल में होने वाली घटनाओं को संग्रहित करने से आपको लचीलापन मिल जाता है।

किसी घटना मॉडल होने से कैलेंडर पर या तारीख खोज फ़िल्टर के साथ ईवेंट को प्रदर्शित करना बहुत आसान हो जाता है क्योंकि आपको केवल घटनाओं के लिए पूछताछ करने की आवश्यकता होती है और फिर किसी भी तिथि में सभी घटनाओं को इकट्ठा करने के बजाय संबंधित ईवेंट का डेटा प्रदर्शित करना आसान होता है रेंज और फिर उन कार्यक्रमों को फ़िल्टर करना है जहां शेड्यूल मेल नहीं खाते हैं।

इसके अलावा

आप कर सकते हैं झंडा एक घटना घटना के रूप में रद्द कर दिया या इसे संशोधित (गलत में उत्पन्न विशेषता सेटिंग तो यह साफ नहीं हो एक ice_cube अनुसूची संपादित करते हुए ... या जो कुछ भी अपने व्यापार की जरूरत है)

के

बेशक यदि आपके पास ऐसी घटनाएं हैं जो अनिश्चित काल तक दोहराती हैं, तो आप भविष्य में कितनी दूर रहना चाहते हैं कि आप उन घटनाओं को उत्पन्न करना चाहते हैं और पुराने रेक को साफ करने और अगले वर्ष या उससे भी अधिक घटनाओं को उत्पन्न करने के लिए स्वचालित रेक कार्यों का उपयोग करना चाहते हैं।

अभी तक यह पैटर्न मेरे लिए बहुत अच्छा काम करता है।

इसके अलावा, recurring_select मणि पर एक नज़र डालें जो एक सुंदर साफ बर्फ_cube फॉर्म इनपुट है।

+2

अच्छी पोस्ट। इस दृष्टिकोण के साथ अपने विचारों पर उत्सुक: http://blog.plataformatec.com.br/2010/04/recurring-events आपके जैसा दिखता है। – Bruno

+0

ब्रूनो, जिस दृष्टिकोण का आप उल्लेख करते हैं वह तब तक वैध है जब तक आपको इन पुनरावर्तनों पर राज्य जारी रखने की आवश्यकता नहीं है या अपवादों से निपटने की आवश्यकता नहीं है (यानी: बारिश के मामले में अगले दिन संगीत कार्यक्रम का प्रतिनिधित्व किया जाता है) – Jim

+0

@Jim क्या आपके पास डेमो है ऐप या उदाहरण ऐप है कि मैं इसके साथ गड़बड़ कर सकता हूँ ?? मुझे आपको समाधान पसंद है – Frank004

-1

मैं रेल के लिए काफी नया हूं, आपका समाधान दिलचस्प लगता है। अनुसूची और संबंधित अवसरों को बनाने के लिए, क्या आप इवेंट मॉडल में सशर्त कॉलबैक का उपयोग करते हैं?

मेरे मामले में, उपयोगकर्ता ईवेंट बनाने, साप्ताहिक आवर्ती या नहीं कर पाएंगे। तो मैं घटना मॉडल में आवर्ती बूलियन क्षेत्र के बारे में सोच रहा था। तो मुझे लगता है कि आप अनुसूची बनाने के लिए पहली बार एक कॉलबैक होगा: आवृत्तियां बनाने के लिए

before_save :create_weekly_schedule, if: :recurring 

और मूल रूप से एक दूसरे से एक:

after_save :create_occurences_if_recurring 

def create_occurences_if_recurring 
    schedules.each do |sched| 
    occurences.create(start_date: sched.start_time, end_date: sched.end_time) 
    end 
end 

इस ध्वनि अपने समाधान के साथ तार्किक करता है? Thx

+1

मुझे लगता है कि आप [मेरे उत्तर] (http://stackoverflow.com/a/10266450/578288) का जवाब दे रहे थे। जब आप किसी विशिष्ट उत्तर का उत्तर देते हैं, तो आपको उस उत्तर पर एक टिप्पणी पोस्ट करनी चाहिए, अन्यथा लेखक को अधिसूचित नहीं किया जाएगा। इसके अलावा, यदि आपका प्रश्न लंबा है (इस तरह), तो मूल प्रश्न पर इसे किसी अन्य उत्तर में न रखें; उस साइट पर एक नया प्रश्न बनाएं जो उस उत्तर से लिंक करता है जिसका आप जवाब दे रहे हैं। –

+0

जो मैं आपके समाधान के बारे में सोचता हूं, उसके लिए मुझे एक समस्या दिखाई देती है। आप 'शेड्यूल.एच' कहते हैं - लेकिन यदि शेड्यूल बस "हर हफ्ते दोहराता है", तो 'प्रत्येक' लूप हमेशा के लिए चलेगा, क्योंकि शेड्यूल एक समाप्ति तिथि निर्दिष्ट नहीं करता है। यही कारण है कि मैंने समय से पहले सभी घटनाएं उत्पन्न नहीं की - उनमें से एक अनंत संख्या है। –

संबंधित मुद्दे