tutorial rails full example event ejemplos ruby-on-rails ruby-on-rails-3 calendar fullcalendar recurring-events

ruby-on-rails - example - fullcalendar in rails



Eventos recurrentes en el calendario-Carriles (4)

Estoy buscando la mejor manera de modelar eventos recurrentes. Estoy usando el calendario completo para mostrar eventos. Pero supongo que los eventos recurrentes se manejan mejor en el backend de los rieles.

Ya miré otras preguntas y código de ejemplo existente, pero no encontré nada que encajara.

Debe comportarse similar al calendario de google. Por lo tanto, debería ser posible eliminar / modificar eventos individuales de la serie de eventos recurrentes. Pero guardar todos los eventos de la serie de eventos en la base de datos parece ineficiente. También debería ser posible crear eventos individuales sin ninguna recurrencia.

¿Cuál sería una buena arquitectura modelo?

Mi modelo de evento ahora se ve así ( sin atributos adicionales ):

# 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


Así es como yo modelaría esto. No he usado Google Calendar mucho, así que estoy basando la funcionalidad de los eventos recurrentes de iCal .

Todos los modelos deben tener las propiedades habituales de id, created_at, updated_at. Se enumeran las propiedades personalizadas. Si la propiedad es otro modelo, implementará una asociación como has_one o belongs_to .

  • RecurrencePeriod
    • Event base_event # has_one :base_event, :class_name''Event''
    • Time end_date # puede ser nil, si se repite para siempre
    • WeeklyRecurrence recurrence # has_one :recurrence, :as=>:recurrence
    • Array[OccurrenceOverride] anula # has_many :overrides, :class_name=>''OccurrenceOverride''

RecurrencePeriod comienza en la fecha en que comienza su base_event. Además, asumo que el employee_id de un Event refiere al empleado que creó ese evento. Un Período de RecurrencePeriod también pertenecerá al empleado que creó el evento base_evento.

El modelo depende de la flexibilidad con la que desee poder especificar las recurrencias. ¿Va a admitir "martes y jueves cada dos semanas de 10 a.m. a 11 a.m. y de 2 a.m. a 3 p.m. ''o simplemente'' se repite semanalmente ''? Aquí hay un modelo que admite solo "repeticiones semanales", "repeticiones cada dos semanas", etc .; Puedes expandirlo si lo necesitas.

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

Utilizo asociaciones polimórficas aquí, porque creo que podrían ser útiles si desea más de un tipo de recurrencia, como WeeklyRecurrence y DailyRecurrence . Pero no estoy seguro de que sean la forma correcta de modelar eso, por lo que si no lo son, simplemente usa has_one :weekly_recurrence y belongs_to :recurrence_period lugar.

La biblioteca de cubitos de hielo parece que podría ser útil para calcular las recurrencias. Si WeeklyRecurrence anterior no es lo suficientemente potente, es posible que solo desee almacenar un objeto Schedule cubo de hielo en un modelo, reemplazando WeeklyRecurrence . Para almacenar un objeto Schedule en un modelo, guárdelo como un atributo "schedule", coloque serialize :schedule en la definición del modelo y genere una columna de texto "schedule" en la base de datos.

OccurrenceOverride maneja el caso de una única instancia de un evento recurrente que se está editando.

  • OccurrenceOverride
    • RecurrencePeriod recurrence_period_to_override # belongs_to :recurrence_period_to_override, :class_name=>''RecurrencePeriod''
    • Time original_start_time # identifica de forma única la recurrencia dentro de ese RecurrencePeriod para reemplazar
    • Event replacement_event # has_one :replacement_event, :class_name=>''Event'' ; puede ser nulo, si esa repetición se eliminó en lugar de editarse

En lugar de almacenar cada evento de un evento individualmente, genérelos temporalmente cuando necesite mostrarlos en la vista. En RecurrencePeriod , cree un método generate_events_in_range(start_date, end_date) que genere Event , no para guardar en la base de datos, sino solo para pasar a la vista para que pueda mostrarlos.

Cuando un usuario edita una repetición, debe tener la opción de modificar todas las ocurrencias, todas las ocurrencias futuras o solo ese evento. Si modifican todas las ocurrencias, modifique el base_event de RecurrencePeriod . Si modifican todas las ocurrencias futuras, use un método que debería implementar en RecurrencePeriod que se divide en dos RecurrencePeriod a cada lado de una fecha determinada, y luego guarde los cambios solo en el segundo período. Si solo modifican ese evento, cree un cambio de OccurrenceOverride para el momento en que están anulando, y guarde los cambios en el evento_reemplazado de la anulación.

Cuando un usuario dice que un determinado evento ahora debe repetirse cada dos semanas en el futuro inmediato, debe crear un nuevo Período de RecurrencePeriod con ese evento como base_event y con una fecha de finalización nula. Su recurrencia debería ser una nueva WeeklyRecurrence con weeks_between_recurrence = 2, y no debería tener ninguna OccurrenceOverride .


En mi caso hice algo como esto:

# 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

A partir de ahí, usé ice_cube para administrar el cálculo de ocurrencias y almacené los resultados en la tabla de ocurrencias. Primero intenté trabajar sin el modelo de ocurrencia, pero no importa qué tan avanzado sea el motor de reglas, siempre tendrá excepciones, por lo que almacenar las ocurrencias en su propio modelo le brinda flexibilidad.

Tener un modelo de ocurrencia hace que sea mucho más fácil mostrar los eventos en un calendario o con filtros de búsqueda de fecha, ya que solo necesita consultar las ocurrencias y luego mostrar los datos del evento relacionado en lugar de recopilar todos los eventos en un rango de fechas determinado y luego para filtrar los eventos donde los horarios no coinciden.

También puede marcar un evento como cancelado o modificarlo (establecer el atributo generado en falso para que no se limpie al editar un programa de ice_cube ... o lo que sea que necesite para su negocio)

Por supuesto, si tiene eventos que se repiten indefinidamente, querrá limitar la cantidad de sucesos que desea que se generen en el futuro y utilizar tareas de rake automatizado para limpiar los antiguos y generar los sucesos para el próximo año.

Hasta ahora, este patrón funciona bastante bien para mí.

Además, eche un vistazo a la gema recurring_select que es una entrada de formulario ice_cube bastante limpia.


Solo una opinión desde lo alto de mi cabeza, tal vez los comentadores señalarán un problema en el que no estoy pensando en este momento:

Haría un modelo RecurringEvent (o como quiera llamarlo) que tiene has_many :events .

Digamos que cada evento es creado por un empleado (basado en sus notas), luego RecurringEvent también belong_to :employee . Luego puede crear un has_many :through relación en la que un empleado tiene muchos eventos y muchos eventos recurrentes.

El modelo RecurringEvent podría tener una fecha de inicio y un patrón, e inicialmente podría usar este patrón para crear los eventos individuales. Luego, en cualquier evento que forme parte de la serie recurrente, puede modificar o eliminar esa ocurrencia individual, pero también puede ''regenerar la serie'', eliminando todos los eventos de la serie (o todos los eventos futuros de la serie) y reconstruyéndolos basándose en un nuevo patrón, por ejemplo, mover la reunión de "todos los martes" a "todos los jueves".

Otra cosa agradable sobre esto es que podría crear una lista de eventos recurrentes de un vistazo, lo que podría darle una buena idea de las principales obligaciones de las personas.

Como dije, fuera de mi cabeza, así es como lo abordaría, pero esto es solo una idea y no he construido nada de eso, así que no sé si hay grandes problemas en el enfoque que tengo. sugerencia.

Buena suerte, por favor publica lo que terminas haciendo!


Soy bastante nuevo en Rails, su solución suena interesante. Para crear la programación y los eventos asociados, ¿utiliza devoluciones de llamada condicionales en el modelo de evento?

En mi caso, los usuarios podrían crear eventos, semanales o no. Así que estaba pensando en un campo booleano recurrente en el modelo de evento. Así que supongo que tendrías una primera devolución de llamada para crear el horario:

before_save :create_weekly_schedule, if: :recurring

y básicamente un segundo para crear las ocurrencias:

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

¿Esto suena lógico con tu solución? Gracias