ruby 53 lines · 10 steps

Building an iCalendar file in Ruby

A small class assembles event details into the RFC 5545 .ics text format, handling escaping and line folding.

Explained by highlit
1require "securerandom"
2require "time"
3 
4class ICalEvent
5 PRODID = "-//Acme Corp//Booking System//EN"
6 
7 def initialize(details)
8 @summary = details.fetch(:summary)
9 @starts_at = details.fetch(:starts_at)
10 @ends_at = details.fetch(:ends_at)
11 @description = details[:description]
12 @location = details[:location]
13 @organizer = details[:organizer]
14 @uid = details[:uid] || "#{SecureRandom.uuid}@acme.corp"
15 end
16 
17 def to_ics
18 lines = [
19 "BEGIN:VCALENDAR",
20 "VERSION:2.0",
21 "PRODID:#{PRODID}",
22 "CALSCALE:GREGORIAN",
23 "METHOD:PUBLISH",
24 "BEGIN:VEVENT",
25 "UID:#{@uid}",
26 "DTSTAMP:#{format_time(Time.now)}",
27 "DTSTART:#{format_time(@starts_at)}",
28 "DTEND:#{format_time(@ends_at)}",
29 "SUMMARY:#{escape(@summary)}"
30 ]
31 lines << "DESCRIPTION:#{escape(@description)}" if @description
32 lines << "LOCATION:#{escape(@location)}" if @location
33 lines << "ORGANIZER:mailto:#{@organizer}" if @organizer
34 lines << "END:VEVENT"
35 lines << "END:VCALENDAR"
36 lines.map { |line| fold(line) }.join("\r\n") + "\r\n"
37 end
38 
39 private
40 
41 def format_time(time)
42 time.utc.strftime("%Y%m%dT%H%M%SZ")
43 end
44 
45 def escape(text)
46 text.to_s.gsub("\\", "\\\\").gsub("\n", "\\n").gsub(/([,;])/, '\\\\\1')
47 end
48 
49 def fold(line)
50 return line if line.bytesize <= 75
51 line.scan(/.{1,74}/m).join("\r\n ")
52 end
53end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Text-based interchange formats are often just carefully assembled and escaped strings, not opaque binaries.
  2. 2Distinguishing required fields (fetch) from optional ones (bracket access) makes an object's contract explicit.
  3. 3Standards like iCalendar carry quirks — UTC timestamps, comma escaping, 75-octet line folding — that you must honor for interoperability.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building an iCalendar file in Ruby — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code