Подтвердить что ты не робот

Повторяющиеся события в календаре - Rails

Я ищу лучший способ моделирования повторяющихся событий. Я использую fullcalendar для отображения событий. Но я думаю, что повторяющиеся события лучше всего обрабатывать на бэкэнде рельсов.

Я уже рассмотрел другие вопросы и существующий пример кода, но я не нашел ничего подходящего.

Он должен вести себя аналогично Google Calendar. Поэтому должно быть возможно удалить/изменить отдельные события повторяющихся серий событий. Но сохранение всех событий серии событий в базе данных кажется неэффективным. Также должно быть возможно создать отдельные события без каких-либо повторений.

Что было бы хорошей модельной архитектурой?

Моя модель событий теперь выглядит так (без дополнительных атрибутов):

# 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
4b9b3361

Ответ 1

Вот как я смогу это моделировать. Я не использовал Календар Google много, поэтому я основываю функциональность от iCal повторяющихся событий.

Все модели должны иметь обычные свойства id, created_at, updated_at. В списке указаны настраиваемые свойства. Если свойство является другой моделью, вы реализуете его как ассоциацию, такую ​​как has_one или belongs_to.

  • RecurrencePeriod
    • Event base_event # has_one :base_event, :class_name'Event'
    • Time end_date # может быть nil, если он повторяется навсегда
    • WeeklyRecurrence повторение # has_one :recurrence, :as=>:recurrence
    • Array[OccurrenceOverride] переопределяет # has_many :overrides, :class_name=>'OccurrenceOverride'

RecurrencePeriod начинается с даты начала его base_event. Кроме того, я предполагаю, что Event employee_id относится к сотруднику, который создал это событие. A RecurrencePeriod также будет принадлежать сотруднику, который создал base_event.

Модель зависит от того, насколько гибко вы хотите указать повторяемость. Будете ли вы поддерживать "вторник и четверг каждые две недели с 10:00 до 11:00 и с 14:00 до 15:00" или просто "повторяется еженедельно"? Здесь модель, которая поддерживает только "повторяется еженедельно", "повторяется каждые две недели" и т.д.; вы можете расширить его, если вам нужно.

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

Я использую полиморфные ассоциации здесь, потому что я думаю, что они могут быть полезны, если вы хотите больше одного типа повторения, таких как WeeklyRecurrence и DailyRecurrence. Но я не уверен, что это правильный способ моделирования, поэтому, если они не окажутся, просто используйте has_one :weekly_recurrence и belongs_to :recurrence_period.

Библиотека Ice cube кажется, что она может быть полезна для вычисления повторений. Если WeeklyRecurrence выше недостаточно мощно, вы можете просто захотеть сохранить объект Ice cube Schedule в модели, заменив WeeklyRecurrence. Чтобы сохранить объект 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'; может быть nil, если это повторение было удалено вместо отредактированного

Вместо того, чтобы хранить каждое событие события индивидуально, создавайте их временно, когда вам нужно показать их в представлении. В RecurrencePeriod создайте метод generate_events_in_range(start_date, end_date), который генерирует Event s, а не сохраняет в базе данных, а просто для перехода к представлению, чтобы он мог их показать.

Когда пользователь редактирует повторение, они должны иметь возможность изменять все вхождения, все будущие вхождения или просто это событие. Если они изменяют все вхождения, измените RecurrencePeriod base_event. Если они изменяют все будущие вхождения, используйте метод, который вы должны реализовать на RecurrencePeriod, который разбивается на две RecurrencePeriod по обе стороны от определенной даты, а затем сохраняет изменения только во второй период. Если они изменяют только это событие, создайте OccurrenceOverride за время, когда они переопределяют, и сохраните изменения в переопределении replace_event.

Когда пользователь говорит, что определенное событие должно повторяться каждые две недели в обозримом будущем, вы должны создать новый RecurrencePeriod с этим событием как base_event и nil end_date. Его повторение должно быть новым WeeklyRecurrence с weeks_between_recurrence = 2, и оно не должно иметь OccurrenceOverride s.

Ответ 2

В моем случае я сделал что-то вроде этого:

# Holds most of my event 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 для управления вычислением вхождений и сохранил результаты в таблице вхождения. Сначала я попытался работать без модели Occurrence, но независимо от того, насколько продвинутый механизм правил, у вас всегда будут исключения, поэтому сохранение вхождений в их собственной модели дает вам гибкость.

Наличие модели Occurrence позволяет намного легче отображать события в календаре или с фильтрами поиска по дате, поскольку вам просто нужно запрашивать события, а затем отображать связанные данные событий, а не собирать все события в заданном диапазоне дат и затем необходимо отфильтровать события, в которых расписание (расписания) не совпадают.

Также вы можете отметить событие как отмененное или изменить его (установка сгенерированного атрибута на false, чтобы он не очищался при редактировании графика ice_cube... или независимо от потребностей вашего бизнеса)

Конечно, если у вас есть события, которые повторяются на неопределенный срок, вы хотите ограничить, как далеко в будущем вы хотите, чтобы эти события были сгенерированы, и использовать автоматические задачи рейка для очистки старых и создания случаев на следующий год или поэтому.

Пока эта модель работает очень хорошо для меня.

Кроме того, посмотрите на recurring_select, который является довольно аккуратным вводом формы ice_cube.

Ответ 3

Просто мнение от моей головы, возможно, коммантеры укажут на проблему, о которой я сейчас не думаю:

Я бы сделал модель RecurringEvent (или все, что вы хотите назвать), что has_many :events.

Предположим, что каждое событие создается сотрудником (на основе ваших заметок), тогда RecurringEvent также будет belong_to :employee. Затем вы могли бы построить связь has_many :through, где у сотрудника много событий и много повторяющихся событий.

Модель RecurringEvent может иметь дату начала и шаблон, и первоначально она могла бы использовать этот шаблон для создания отдельных событий. Затем на любом событии, которое является частью повторяющейся серии, вы можете изменить или удалить это отдельное событие, но вы также можете "восстановить серию", удалив все события из серии (или все будущие события в серии) и перестроя их на основе новый шаблон, поэтому, например, переместите встречу с "каждый вторник" на "каждый четверг".

Еще одна приятная вещь об этом - вы можете создать обзорный список повторяющихся событий, что может дать вам некоторое представление о важных обязательствах людей.

Как я уже сказал, с моей точки зрения, что я подхожу к нему, но это всего лишь идея, и я не создал ничего подобного, поэтому я не знаю, есть ли какие-то большие проблемы в подходе Я предлагаю.

Удачи, пожалуйста, напишите, что вы в итоге делаете!

Ответ 4

Я совершенно новый для Rails, ваше решение звучит интересно. Чтобы создать расписание и связанные с ним вхождения, вы используете условные обратные вызовы в модели событий?

В моем случае пользователи смогут создавать события, еженедельно повторяющиеся или нет. Поэтому я думал о повторяющемся булевом поле в модели событий. Поэтому, я думаю, у вас будет первый обратный вызов для создания расписания:

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

Является ли это логичным с вашим решением? спасибо