#94
Recurring Events with FullCalendar
8-20-2017
Summary
Create recurring events and interact with them on FullCalendar.
6
rails
view
calendar
javascript
ajax
8:30
Summary
Create recurring events and interact with them on FullCalendar.
6
Resources
Be sure to checkout the previous episodes as they cover much of the prerequisite information.
Episode 42 - Full Calendar Events and Scheduling
Episode 93 - Recurring Events with ice_cube
Source - https://github.com/driftingruby/094-recurring-events-on-full-calendar
Summary
Gemfilesource 'https://rails-assets.org' do
gem 'rails-assets-fullcalendar'
gem 'rails-assets-momentjs'
end
gem 'ice_cube'
recurring_events_migration.rb# rails g model recurring_event title anchor:date frequency:integer color
class CreateRecurringEvents < ActiveRecord::Migration[5.0]
def change
create_table :recurring_events do |t|
t.string :title
t.date :anchor
t.integer :frequency, limit: 1, default: 0
t.string :color
t.timestamps
end
end
endrecurring_events_controller.rbclass RecurringEventsController < ApplicationController
before_action :set_recurring_event, only: [:show, :edit, :update, :destroy]
def index
@recurring_events = RecurringEvent.all
end
def show
end
def new
@recurring_event = RecurringEvent.new
end
def edit
end
def create
@recurring_event = RecurringEvent.new(recurring_event_params)
@recurring_event.save
end
def update
if params[:event]
@recurring_event.update(anchor: params[:event][:start])
else
@recurring_event.update(recurring_event_params)
end
end
def destroy
@recurring_event.destroy
end
private
def set_recurring_event
@recurring_event = RecurringEvent.find(params[:id])
end
def recurring_event_params
params.require(:recurring_event).permit(:title, :anchor, :frequency, :color)
end
endrecurring_event.rbclass RecurringEvent < ApplicationRecord
enum frequency: { weekly: 0, biweekly: 1, monthly: 2, annually: 3 }
validates :anchor, presence: true
validates :frequency, presence: true
def schedule
@schedule ||= begin
schedule = IceCube::Schedule.new(now = anchor)
case frequency
when 'weekly'
schedule.add_recurrence_rule IceCube::Rule.weekly(1)
when 'biweekly'
schedule.add_recurrence_rule IceCube::Rule.weekly(2)
when 'monthly'
schedule.add_recurrence_rule IceCube::Rule.monthly(1)
when 'annually'
schedule.add_recurrence_rule IceCube::Rule.yearly(1)
end
schedule
end
end
def events(start_date, end_date)
start_frequency = start_date ? start_date.to_date : Date.today - 1.year
end_frequency = end_date ? end_date.to_date : Date.today + 1.year
schedule.occurrences_between(start_frequency, end_frequency)
end
endfull_calendar.jsvar initialize_calendar;
initialize_calendar = function() {
$('.calendar').each(function(){
var calendar = $(this);
calendar.fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
selectable: true,
selectHelper: true,
editable: true,
eventLimit: true,
eventSources: [
'/events.json',
'/recurring_events.json'
],
select: function(start, end) {
$.getScript('/events/new', function() {
$('#event_date_range').val(moment(start).format("MM/DD/YYYY HH:mm") + ' - ' + moment(end).format("MM/DD/YYYY HH:mm"))
date_range_picker();
$('.start_hidden').val(moment(start).format('YYYY-MM-DD HH:mm'));
$('.end_hidden').val(moment(end).format('YYYY-MM-DD HH:mm'));
});
calendar.fullCalendar('unselect');
},
eventDrop: function(event, delta, revertFunc) {
event_data = {
event: {
id: event.id,
start: event.start.format(),
end: event.end.format()
}
};
$.ajax({
url: event.update_url,
data: event_data,
type: 'PATCH'
});
},
eventClick: function(event, jsEvent, view) {
$.getScript(event.edit_url, function() {
$('#event_date_range').val(moment(event.start).format("MM/DD/YYYY HH:mm") + ' - ' + moment(event.end).format("MM/DD/YYYY HH:mm"))
date_range_picker();
$('.start_hidden').val(moment(event.start).format('YYYY-MM-DD HH:mm'));
$('.end_hidden').val(moment(event.end).format('YYYY-MM-DD HH:mm'));
});
}
});
})
};
$(document).on('turbolinks:load', initialize_calendar);index.json.jbuilderjson.partial! @recurring_events,
partial: 'recurring_events/recurring_event',
as: :recurring_event
_recurring_event.json.jbuilderevents = recurring_event.events(params[:start], params[:end])
json.array! events do |event|
json.id "recurring_#{recurring_event.id}"
json.title recurring_event.title
json.start event.strftime('%Y-%m-%d')
json.end (event + 1.day).strftime('%Y-%m-%d')
json.color recurring_event.color unless recurring_event.color.blank?
json.allDay true
json.update_url recurring_event_path(recurring_event, method: :patch)
json.edit_url edit_recurring_event_path(recurring_event)
endupdate.js.erb$('.calendar').fullCalendar('removeEvents', '<%= "recurring_#{@recurring_event.id}" %>');
$('.calendar').fullCalendar(
'renderEvents',
$.parseJSON("<%= j render(@recurring_event, format: :json).html_safe %>"),
true
);
$('.modal').modal('hide');
Great Episode! Can you please make an episode where you integrate search for recurring records? Im using ice_cube and want to create a recurring object and then search for different instances of it based on start_date and end_date lets say. As of now im creating a different object for each recurrence which is highly inefficient, but was having problems searching for the recurrences of the object based on date and filtering and also updating and showing on full calendar. Im sorry if im not very clear. i hope you get an idea about what i want to achieve! Thank you so much again for all your episodes! I've learned a lot watching your episodes. Thanks for doing them and keeping them free!
Olsi