Webcal Links in Rails with the icalendar Gem
The icalendar gem is a useful way to generate iCalendar files for use with various calendar applications. One thing I couldn't find good documentation on, though, is how to use it to create a Webcal link in a Ruby on Rails app, so I figured I'd would go ahead and document that myself.
Before I get started, I'll just mention that all of the code examples in this post are from the demo app, which you can find on Github. Also, the demo app is live, so you can see everything in action.
Webcal
Webcal is what allows a user to click on a link in their browser to subscribe to a calendar in their calendar app.
So, you click on a link in your browser, then a dialog window pops up in your calendar app to subscribe to the calendar:
Then you click Subscribe and, voilà, now that power lunch you have scheduled is in your calendar:
In the future, your calendar app will periodically poll the calendar's URL to check for updates.
Controller
Here's what your controller should look like:
class CalendarsController < ApplicationController
def show
respond_to do |format|
format.ics do
cal = Icalendar::Calendar.new
cal.x_wr_calname = 'Awesome Rails Calendar'
cal.event do |e|
e.dtstart = DateTime.now + 2.hours
e.dtend = DateTime.now + 3.hours
e.summary = 'Power Lunch'
e.description = 'Get together and do big things'
end
cal.publish
render plain: cal.to_ical
end
end
end
end
I'll highlight the important parts:
-
Your controller needs to be unauthenticated, or else the user's calendar app won't be able to access the calendar. So, if your
ApplicationController
is authenticated, yourCalendarsController
will probably need to inherit directly fromActionController::Base
to avoid authentication. -
If your calendar contains sensitive data that should only be available to a specific user, you will need to use a strategy similar to password reset links so that you aren't leaking sensitive data. So, your calendar should be available at a path like
/calendar/u/:some_long_random_string
, instead of/calendar/u/:user_id
. -
You
respond_to
theics
format. -
You set
cal.x_wr_calname
to specify the default calendar name that will be displayed in the user's calendar app. -
You use
render plain: cal.to_ical
to actually render the calendar. In older versions of Rails you would specifytext
instead ofplain
.
You can learn about everything else going on in this controller by reading the icalendar
gem documentation. It's all standard stuff.
Link
Here's what your subscription link should look like:
<%= link_to 'Subscribe', calendar_url(protocol: :webcal, format: :ics) %>
I'll highlight the important parts:
-
You have to use a full URL, not just a path. The reason for this is the same as for Rails mailers: unlike the browser, the user's calendar app won't know the domain. So, in this example, we're using
calendar_url
instead ofcalendar_path
. -
You specify the
webcal
protocol. This will create a link that starts withwebcal://
, instead ofhttp://
, which is what tells the browser to hand the link off to the user's calendar app. -
You specify the
ics
format. This will create a link that ends in/calendar.ics
, instead of just/calendar
, which is what tells Rails to handle the request with theformat.ics
block in the controller.
That's it, you're done!
Just a reminder that you can find the demo app on Github, or see it in action on Heroku.