Oto, jak mógłbym to modelować. Nie korzystałem zbyt wiele z Kalendarza Google, więc opieram tę funkcję na powtarzających się wydarzeniach z iCal.
Wszystkie modele powinny mieć zwykle id, created_at, updated_at properties. Wymienione są właściwości niestandardowe. Jeśli właściwość to inny model, zaimplementujesz ją jako stowarzyszenie, takie jak has_one
lub belongs_to
.
RecurrencePeriod
Event
base_event # has_one :base_event, :class_name'Event'
Time
end_date # może być zerowa, jeśli powtarza się zawsze
WeeklyRecurrence
nawrót # has_one :recurrence, :as=>:recurrence
Array[OccurrenceOverride]
zastępuje # has_many :overrides, :class_name=>'OccurrenceOverride'
W RecurrencePeriod
rozpoczyna się w dniu, w którym rozpoczyna base_event. Zakładam również, że pracownik employee Event
odnosi się do pracownika, który utworzył to wydarzenie. Numer RecurrencePeriod
również należy do pracownika, który utworzył element base_event.
Model zależy od tego, jak elastycznie chcesz móc określać nawroty. Czy zamierzasz wesprzeć "we wtorek i czwartek co dwa tygodnie od 10 rano do 11 rano i od 2 po południu do 3 po południu" lub po prostu "powtarza co tydzień"? Oto model, który obsługuje po prostu "powtarza się co tydzień", "powtarza się co dwa tygodnie", itd .; możesz ją rozwinąć, jeśli potrzebujesz.
WeeklyRecurrence
Integer
weeks_between_recurrences
RecurrencePeriod
RECURRENCE_PERIOD # belongs_to :recurrence, :polymorphic=>true
używam polymorphic associations tutaj, ponieważ myślę, że mogą one być przydatne, jeśli chcesz więcej niż jeden typ nawrotów, takich jak WeeklyRecurrence
i DailyRecurrence
. Ale nie jestem pewien, czy to jest właściwy sposób modelowania tego, więc jeśli nie są, po prostu użyj has_one :weekly_recurrence
i belongs_to :recurrence_period
.
Biblioteka Ice cube wydaje się być przydatna do obliczania nawrotów. Jeśli powyższe WeeklyRecurrence
nie jest wystarczająco wydajne, możesz po prostu zapisać obiekt kostki lodu Schedule
w modelu, zastępując WeeklyRecurrence
. Aby zapisać obiekt Schedule
w modelu, zapisz go jako atrybut "harmonogram", wstaw serialize :schedule
do definicji modelu i wygeneruj kolumnę tekstową "harmonogram" w bazie danych.
OccurrenceOverride
obsługuje przypadek pojedynczej instancji edytowanego wydarzenia cyklicznego.
OccurrenceOverride
RecurrencePeriod
recurrence_period_to_override # belongs_to :recurrence_period_to_override, :class_name=>'RecurrencePeriod'
Time
original_start_time # jednoznacznie identyfikuje których nawrót w tym RecurrencePeriod zastąpić
Event
replacement_event # has_one :replacement_event, :class_name=>'Event'
; może być zerowa, jeśli nawrót został skasowany zamiast edytowany
Zamiast przechowywać każde wystąpienie zdarzenia indywidualnie, generują je tymczasowo, gdy trzeba pokazać je w widoku. W wersji RecurrencePeriod
utwórz metodę generate_events_in_range(start_date, end_date)
, która generuje Event
s, aby nie zapisywać w bazie danych, ale po prostu przekazać do widoku, aby mógł je wyświetlić.
Gdy użytkownik edytuje powtarzanie, powinien mieć możliwość modyfikacji wszystkich wystąpień, wszystkich przyszłych wystąpień lub tylko tego zdarzenia Jeśli zmodyfikują wszystkie wystąpienia, zmodyfikuj element base_event RecurrencePeriod
. Jeśli zmodyfikują wszystkie przyszłe wystąpienia, użyj metody, którą należy wdrożyć na RecurrencePeriod
, która dzieli się na dwie części RecurrencePeriod
po dowolnej stronie określonej daty, a następnie zapisz zmiany tylko do drugiego okresu. Jeśli modyfikują tylko to zdarzenie, utwórz OccurrenceOverride
na czas, który nadpisują, i zapisz zmiany w zastąpieniu_wystąpienia.
Gdy użytkownik mówi, że pewne zdarzenie powinno się teraz powtarzać co dwa tygodnie w przewidywalnej przyszłości, należy utworzyć nowe RecurrencePeriod
z tym zdarzeniem jako element base_event i nil data_końcową. Jego powtarzanie powinno być nowe: WeeklyRecurrence
z weeks_between_recurrence = 2 i nie powinno mieć żadnych s. OccurrenceOverride
.
Jakiekolwiek problemy z doświadczeniem, które nie spowodowały wystąpienia zdarzenia, chociaż nie można uzyskać do niego dostępu za pomocą identyfikatora? (wydajność, złożoność itp.) – ted
@ted Dobre pytanie. Nigdy tego nie wdrożyłem, więc obawiam się, że nie wiem, czy generowanie zdarzeń w razie potrzeby powoduje problemy. Przypuszczam, że w razie potrzeby można skonfigurować pamięć podręczną dla wygenerowanych wystąpień. System buforowania może wykorzystywać fakt, że wygenerowane wystąpienie do zapisania jest konceptualnie bardzo podobne do "WystępowaniaOverride", choć nie jest tożsame. –