While working on a project, I had the need of adding some calendars to display information from events already saved on a RoR application. Fortunately, I had done something similar for a project during my last semester of college using a fantastic Javascript library called FullCalendar created by Adam Shaw.
In this blogpost, I'll guide you through the process of integrating the calendar with an existent Ruby on Rails application by using one of the new features that comes included with Rails 4 by default: jbuilder
Hands on
We are going to create a simple Rails 4 app to demonstrate the integration but, if you already have an application that needs a calendar, this example will also help you. That is because the 'magic' that glues together the calendar with our application lies on what jbuilder does: creating a JSON response
Let's create an scaffold for a model called 'Event' with some attributes to display in our calendar:
rails generate scaffold Event title:string description:text start_time:datetime end_time:datetime
And don't forget to run migrations and run the server:
rake db:migrate
rails server
Now that we are ready, we can navigate to localhost:3000/events and see our brand new event list.
We can see the JSON representation of our events by going to localhost:3000/events.json
Setting up the calendar
We can download the necessary assets from the FullCalendar webpage or using the FullCalendar-rails gem. In case that you, as me, prefer to use it as a gem, we only need to add it our Gemfile
gem 'fullcalendar-rails'
And then run
bundle install
At this point, the files are already in the assets pipeline's path and the final step is to require them in our application.* files:
In application.css.scss
we'll add
*= require fullcalendar
And in our application.js
//= require fullcalendar
In order to feed our calendar, we need to create some events either from the web interface created by the scaffold or using the Rails console: I will leave this part up to you.
We need to create a div in our view and initialize the calendar using jQuery:
$('#calendar').fullCalendar();
And we have our fullCalendar up and running:
Note: I made it smaller using CSS: by default, the calendar takes all the width available
Let's move to the backend
Now that our calendar looks awesome, we need to work on how the events are going to be displayed and, yes, it is time to move on to Rails.
There are many ways to load our events in the calendar but the most interesting and useful for this example is to provide the calendar with a URL where it can get the events as a JSON array. This array will look similar to this:
[
{
title : 'event1',
start : '2010-01-01'
},
{
title : 'event2',
start : '2010-01-05',
end : '2010-01-07'
},
{
title : 'event3',
start : '2010-01-09 12:30:00',
allDay : false
}
]
We need to make sure to return our JSON according to this format, this is where jbuilder will help us.
The JSON way
The scaffold we used to generate the application has already provided us with a handy way of adding JSON support: we can take a look at app/views/events/index.json.builder
file and see the default format it provides:
json.array!(@events) do |event|
json.extract! event, :id, :title, :description, :start_time, :end_time
json.url event_url(event, format: :json)
end
It just takes all the events and its attributes and creates an array. We can see the output by visiting localhost:3000/events.json
So close! It looks very similar to the format fullCalendar expects but we need to make a couple of changes to make it match:
json.array!(@events) do |event|
json.extract! event, :id, :title, :description
json.start event.start_time
json.end event.end_time
json.url event_url(event, format: :html)
end
We had to rename the start\time_ and end\time_ to start and end.
Additionally, we changed the format of the URL attribute from :json to :html. I'll explain this in the next step.
Our new output will look similar to this:
When frontend meets backend
Now that our backend provides us with a JSON response in the same format that fullCalendar needs, we need to go back where we initialized our fullCalendar and send the proper params:
$('#calendar').fullCalendar(
events: '/events.json'
);
And we are done! now our calendar shows the events we have added:
Remember the change we did in the index.json.builder file about pointing our URL attribute to its HTML version instead of the JSON one? We'll, this change allows us to point to our '/events/{id}.html' route when we click on an event.
Wrapping up
It is worth to notice that you are not tied to using jbuilder for creating the JSON response: you can use ActiveModel::Serializer, Rabl or whatever that fits your application needs… or even better, you could use fullCalendar without RoR, another framework or even a different language might work. The key for the integration is to follow the JSON format that fullCalendar requires.
I really encourage you to read the documentation to know about all the customization that fullCalendar supports: it is a very flexible and powerful library and I bet you don't want to miss all the options it provides.
Finally, you can take a look at this example in this github repository specially created for this blogpost.
Thanks for reading!