Download as Markdown llms.txt

CalInvite

CalInvite: calendar invitations for Ruby. Google, Outlook, Apple, Yahoo, .ics

Generate “add to calendar” links and .ics calendar invites from Ruby, for Google Calendar, Outlook, Outlook 365, Yahoo, Apple Calendar, and any client that reads iCalendar files.

Gem Version Build Status License

You describe an event once and get a link or .ics content for each provider. With method: :request, the .ics is an RFC 5545 meeting request that Gmail, Outlook and Apple Mail show with Accept/Decline buttons, and later updates or cancellations replace the original invite. Any IANA timezone gets a full VTIMEZONE with correctly converted times. Attribute values are escaped, so end-user input can’t add properties to an invite.

Contents

Installation

CalInvite is published on RubyGems. It requires Ruby 3.0 or newer. It works with or without Rails, and supports Rails 6.0 through 8.1.

# Gemfile
gem "cal-invite"
bundle install

Quick start

require "cal_invite"

event = CalInvite::Event.new(
  title: "Team Meeting",
  start_time: Time.utc(2026, 11, 2, 15, 0),   # always pass UTC
  end_time:   Time.utc(2026, 11, 2, 16, 0),
  timezone: "America/New_York",               # how the time is displayed
  description: "Weekly sync",
  location: "Conference Room A",              # physical place
  url: "https://zoom.us/j/123456789"          # virtual meeting link
)

event.generate_calendar_url(:google)  # => "https://calendar.google.com/calendar/render?action=TEMPLATE&..."
event.generate_calendar_url(:ics)     # => "BEGIN:VCALENDAR\r\n..." (.ics file content)

Providers

Provider Returns Notes
:google URL Opens Google Calendar’s “add event” page.
:outlook URL Outlook.com (personal accounts).
:office365 URL Outlook on the web for work/school (Microsoft 365) accounts.
:yahoo URL One URL per session for multi-day events, separated by newlines.
:ics .ics content Standard iCalendar file; works with Apple Calendar, Thunderbird, Proton, Fastmail and others.
:ical .ics content Same content as :ics; kept for Apple Calendar naming.

Only :ics and :ical support the method: option (:publish by default, also :request, :cancel, :reply, :counter, :decline_counter). Any other provider name raises ArgumentError.

More examples

# Attendees: email strings, or hashes with a display name and RSVP status
CalInvite::Event.new(
  title: "Planning",
  start_time: Time.utc(2026, 11, 2, 15), end_time: Time.utc(2026, 11, 2, 16),
  attendees: ["bob@example.com", { email: "ada@example.com", name: "Ada", partstat: :accepted }],
  show_attendees: true
)

# All-day event
CalInvite::Event.new(title: "Company Offsite", start_time: Time.utc(2026, 12, 4), all_day: true)

# Recurring event, with a reminder 15 minutes before
CalInvite::Event.new(
  title: "Standup",
  start_time: Time.utc(2026, 11, 2, 14), end_time: Time.utc(2026, 11, 2, 14, 15),
  timezone: "Europe/Paris",
  rrule: "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR",
  reminders: [15]
)

# Multi-day event with separate sessions
CalInvite::Event.new(
  title: "Training Workshop",
  multi_day_sessions: [
    { start_time: Time.utc(2026, 3, 1, 13), end_time: Time.utc(2026, 3, 1, 22) },
    { start_time: Time.utc(2026, 3, 2, 14), end_time: Time.utc(2026, 3, 2, 18) }
  ],
  timezone: "America/New_York",
  location: "Training Center"
)

For a multi-day event, :ics, :ical and :yahoo produce one entry per session. Google and Outlook can only show one range, so they show the whole span, from the first session’s start to the last session’s end.

Every attribute (organizer, geo, busy, visibility, importance, calendar_name, …) is listed in CONFIGURATION.md.

Serving a downloadable .ics file

# app/controllers/events_controller.rb
def calendar
  event = CalInvite::Event.new(...)
  download = CalInvite::Providers::IcsDownload.wrap_for_download(
    event.generate_calendar_url(:ics), event.title
  )

  send_data download[:content],
            type: download[:headers]["Content-Type"],
            filename: "#{CalInvite::Providers::IcsDownload.sanitize_filename(event.title)}.ics",
            disposition: "attachment"
end

Sending email invites with RSVP

A plain .ics attachment opens as a file. To have mail clients show it as a meeting invite with Accept/Decline buttons, you need three things: an organizer, method: :request, and a matching method=REQUEST on the attachment’s content type.

event = CalInvite::Event.new(
  title: "Design Review",
  start_time: Time.utc(2026, 11, 2, 15), end_time: Time.utc(2026, 11, 2, 16),
  organizer: { name: "Jane Doe", email: "jane@example.com" },
  attendees: ["guest@example.com"],
  show_attendees: true
)

# In your ActionMailer method:
attachments["invite.ics"] = {
  mime_type: "text/calendar; method=REQUEST",
  content: event.generate_calendar_url(:ics, method: :request)
}

Save event.uid. To reschedule or cancel later, rebuild the event with the same uid and a higher sequence, then send method: :request again (for a reschedule) or method: :cancel. See Updating and cancelling invites. The example Rails app has a working implementation.

Things to know

Global settings:

# config/initializers/cal_invite.rb
CalInvite.configure do |config|
  config.timezone = "America/New_York"   # default for events that don't set one
end

Upgrading to 0.3.0

0.3.0 is stricter. Unknown attributes, invalid timezones and invalid time ranges now raise ArgumentError, where 0.2.x silently produced a broken invite. The gem also no longer loads all of active_support/core_ext. In plain Ruby, 1.hour and Time.current no longer work unless you require them yourself.

The cache_store/cache_prefix/cache_expires_in settings and the top-level ::BaseProvider constant are deprecated. They still work, but print a warning, and they’ll be removed in 0.4.0. The full list of changes is in CHANGELOG.md.

Documentation

Development

bin/setup                                                  # install dependencies
bundle exec rake test                                      # full suite (+ coverage report in coverage/)
bundle exec rake test TEST=test/cal_invite/event_test.rb   # one file
bin/console                                                # IRB with the local lib/ loaded

To try unreleased changes in the example Rails app, switch its Gemfile to the commented-out gem "cal-invite", path: "../../" line and run bundle install. Switch it back before committing.

To release, bump lib/cal_invite/version.rb, update CHANGELOG.md, merge to main, and push a vX.Y.Z tag. CI then runs the tests, publishes the gem to RubyGems and deploys the docs.

Contributing

Bug reports and pull requests are welcome on GitHub. Please add tests for your change and run bundle exec rake test before opening a PR. To report a security issue, see SECURITY.md. Everyone taking part in the project is expected to follow the code of conduct.

CalInvite is sponsored by DashAPI.

DashAPI

License

Released under the MIT License.