cal-invite 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rdoc_options +5 -1
- data/AGENTS.md +47 -0
- data/CHANGELOG.md +28 -0
- data/CLAUDE.md +49 -0
- data/CONFIGURATION.md +536 -0
- data/README.md +18 -7
- data/SECURITY.md +21 -0
- data/gemfiles/Gemfile.rails6 +3 -0
- data/gemfiles/Gemfile.rails7 +3 -0
- data/gemfiles/Gemfile.rails8 +3 -0
- data/lib/cal_invite/event.rb +103 -9
- data/lib/cal_invite/ical_timezone.rb +132 -0
- data/lib/cal_invite/providers/base_provider.rb +188 -4
- data/lib/cal_invite/providers/ical.rb +23 -24
- data/lib/cal_invite/providers/ics.rb +30 -18
- data/lib/cal_invite/providers/ics_content.rb +33 -22
- data/lib/cal_invite/providers/office365.rb +2 -2
- data/lib/cal_invite/providers/outlook.rb +2 -2
- data/lib/cal_invite/version.rb +1 -1
- data/lib/cal_invite.rb +4 -0
- metadata +69 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1a0ff2de747c18b6c294b6b9a53678ac1199a749a11be93bab4af93b8ab4617d
|
|
4
|
+
data.tar.gz: c08188280a75f0015bfee4f2cd8f896db4ac2294c7df4826bf63e1f72a05e6db
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 83cd15e9cbf2aa3360e353aaf7fcd893fdd73d003a8de959b5c3258230560e4b3d56df060e6589fa3661945471393c085990d0d45628443b08b3eec3fad258db
|
|
7
|
+
data.tar.gz: f0d296b4789394ded4394f884b8a26c3041e47af5b16c7e7891b4317565fb35c72726788f95ce73ec0b7247816c18b4c253534f062535076022c5d337888706b
|
data/.rdoc_options
CHANGED
|
@@ -6,7 +6,7 @@ exclude: ["vendor/*", "tmp/*", ".*/*"]
|
|
|
6
6
|
hyperlink_all: true
|
|
7
7
|
line_numbers: true
|
|
8
8
|
locale: en
|
|
9
|
-
main: README.md
|
|
9
|
+
main: README.md # This makes README.md the main page
|
|
10
10
|
markup: markdown
|
|
11
11
|
output_decoration: true
|
|
12
12
|
show_hash: false
|
|
@@ -16,6 +16,10 @@ title: "CalInvite - Calendar Invite Generator by DashAPI"
|
|
|
16
16
|
visibility: :public
|
|
17
17
|
webcvs: https://github.com/the-pew-inc/cal-invite
|
|
18
18
|
|
|
19
|
+
# Adding explicit index generation
|
|
20
|
+
generate_index: true # Add this line
|
|
21
|
+
index_name: index.html # Add this line
|
|
22
|
+
|
|
19
23
|
# Custom sections for better organization
|
|
20
24
|
sections:
|
|
21
25
|
- title: Calendar Providers
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Guidance for AI coding agents working in this repository.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
CalInvite is a Ruby gem for generating calendar invitations (URLs and .ics files) across multiple platforms: Google, Outlook, Outlook 365, Yahoo, Apple iCal, and generic .ics. Ruby >= 3.0.0, Rails 6.0–8.0 compatible, depends on `activesupport`.
|
|
8
|
+
|
|
9
|
+
## Setup & commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bundle install # install dependencies
|
|
13
|
+
rake test # run full test suite (default rake task)
|
|
14
|
+
rake test TEST=test/cal_invite/event_test.rb # run a single test file
|
|
15
|
+
ruby -Itest -Ilib test/cal_invite/event_test.rb # run a single test file directly
|
|
16
|
+
rake rdoc # generate RDoc documentation into doc/
|
|
17
|
+
rake rdoc:clean # remove generated doc/
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Tests are Minitest-based, files live under `test/cal_invite/`, named `*_test.rb`. Coverage is collected via SimpleCov (see `coverage/`). Always run `rake test` before considering a change complete.
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
|
|
24
|
+
- **`CalInvite` module** (`lib/cal_invite.rb`) — top-level entry point. Holds a singleton `CalInvite.configuration` (a `Configuration` instance) set via `CalInvite.configure { |c| ... }`. Mixes in `Caching` at the module level for class-level cache helpers.
|
|
25
|
+
|
|
26
|
+
- **`CalInvite::Event`** (`lib/cal_invite/event.rb`) — the central object. Holds all event attributes (title, start/end time, location, url, attendees, timezone, notes, multi-day sessions, all-day flag). `generate_calendar_url(provider)` is the main API: it validates the event, checks the cache (MD5 hash of all attributes + provider as key), and if not cached, resolves `CalInvite::Providers::<CapitalizedProvider>`, instantiates it with `self`, and calls `#generate`. Location and virtual-meeting URL are intentionally separate fields (not merged) so each provider can format them appropriately.
|
|
27
|
+
|
|
28
|
+
- **`CalInvite::Providers`** (`lib/cal_invite/providers.rb`) — namespace with `SUPPORTED_PROVIDERS = %i[google ical outlook yahoo ics office365]`. Provider classes are autoloaded from `lib/cal_invite/providers/*.rb`. To add a new provider: create a class extending `BaseProvider`, implement `#generate`, register it here with `autoload`, and add its symbol to `SUPPORTED_PROVIDERS`.
|
|
29
|
+
|
|
30
|
+
- **`BaseProvider`** (`lib/cal_invite/providers/base_provider.rb`) — abstract base class (note: it's a top-level `class BaseProvider`, not namespaced under `CalInvite::Providers`). Defines the `#generate` contract (must raise `NotImplementedError` if not overridden) plus shared helpers used by subclasses: `url_encode`, `format_description`, `format_location`, `format_url`, `format_description_with_url`, `add_optional_params`, `attendees_list`. Each concrete provider (`Google`, `Outlook`, `Office365`, `Yahoo`, `Ical`, `Ics`) builds a provider-specific URL or content string from the `Event` using these helpers.
|
|
31
|
+
|
|
32
|
+
- **`Ics` / `IcsContent` providers** (`ics.rb`, `ics_content.rb`) — generate actual `.ics` file content (RFC 5545) rather than a URL, for direct download flows (see README's `send_data` controller example). `IcsDownload` is aliased to `IcsContent` via autoload.
|
|
33
|
+
|
|
34
|
+
- **`Caching`** (`lib/cal_invite/caching.rb`) — an `ActiveSupport::Concern` mixed into `CalInvite` at the class level. Provides `fetch_from_cache`, `write_to_cache`, `read_from_cache`, `clear_cache!`, `clear_event_cache!`, `clear_provider_cache!`, all keyed under `CalInvite.configuration.cache_prefix`. Works with any `ActiveSupport::Cache::Store`-compatible store, or a custom object responding to `read`/`write`/`delete`. See also `CACHING.md`.
|
|
35
|
+
|
|
36
|
+
- **`Configuration`** (`lib/cal_invite/configuration.rb`) — holds `cache_store`, `cache_prefix` (default `'cal_invite'`), `cache_expires_in` (default 24 hours), `webhook_secret`, `timezone` (default `'UTC'`). `cache_store=` accepts `:memory_store`, `:null_store`, or any object implementing `read`/`write`/`delete`.
|
|
37
|
+
|
|
38
|
+
## Conventions
|
|
39
|
+
|
|
40
|
+
- Always pass times to `Event.new` in UTC; use the `timezone` attribute only to control display/formatting in the generated invite.
|
|
41
|
+
- `location` (physical) and `url` (virtual meeting link) are kept as distinct fields throughout the provider layer — don't conflate them when adding provider logic.
|
|
42
|
+
- All-day events skip `start_time`/`end_time` validation; multi-day events use the separate `multi_day_sessions` array instead of `start_time`/`end_time`.
|
|
43
|
+
- YARD-style doc comments (`@param`, `@return`, `@example`) are used throughout `lib/` and feed the RDoc-generated docs published to GitHub Pages (`.github/workflows/documentation.yml`) — keep them accurate when changing public method signatures.
|
|
44
|
+
|
|
45
|
+
## PRs & commits
|
|
46
|
+
|
|
47
|
+
Gem released via standard Bundler `rake release` flow (`bundler/gem_tasks`). Version lives in `lib/cal_invite/version.rb`; update `CHANGELOG.md` alongside version bumps.
|
data/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,35 @@
|
|
|
1
1
|
# Cal Invite
|
|
2
2
|
|
|
3
|
+
## [v0.2.0] - 2026-08-09
|
|
4
|
+
|
|
5
|
+
- Add `Event#organizer` and a `method:` option (`:publish`/`:request`/`:cancel`) to `generate_calendar_url`, so ics/ical output can carry `METHOD:REQUEST`/`METHOD:CANCEL` + `ORGANIZER`/`SEQUENCE`/`STATUS`, matching what mail clients (Gmail, Outlook, Apple Mail) need to render an attached `.ics` as an RSVP-capable meeting invite (or a real cancellation) rather than a plain file
|
|
6
|
+
- `ATTENDEE` lines now include `CUTYPE`/`ROLE`/`PARTSTAT`
|
|
7
|
+
- `IcsDownload.headers`/`.wrap_for_download` accept `method:` to add the matching `method=REQUEST` Content-Type parameter
|
|
8
|
+
- Fix a `superclass mismatch` crash when both the `:ics` provider and `IcsDownload`/`IcsContent` were loaded (dead duplicate `Ics`/`Ical` class definitions in `ics_content.rb`)
|
|
9
|
+
- **Fix: stable `UID`.** `Event#uid` is now a real attribute (auto-generated and memoized per `Event` instance, or pass your own) instead of the ics/ical/ics_content providers each minting a fresh random UID on every `generate` call — required for mail/calendar clients to recognize a `:request` update or `:cancel` as referring to a previously sent invite rather than a new, unrelated event. See new `Event#sequence` (defaults to `0`) and CONFIGURATION.md's "Updating and cancelling invites".
|
|
10
|
+
- **Fix: real `VTIMEZONE`.** `:ics`/`:ical` now emit a complete `VTIMEZONE` component (`STANDARD`/`DAYLIGHT` observances with correct offsets and `RRULE`s, derived from TZInfo's transition data) for any recognized IANA timezone, instead of an empty/absent block. `DTSTART;TZID=...`/`DTEND;TZID=...` are also now correctly converted from UTC to that zone's local wall-clock time — previously the UTC clock digits were emitted verbatim under a non-UTC `TZID`, mislabeling the time. `'UTC'` continues to use plain `Z`-suffixed timestamps with no `VTIMEZONE`, as before.
|
|
11
|
+
- Add `tzinfo` as an explicit gem dependency (previously relied on it only transitively via `activesupport`).
|
|
12
|
+
- `Event#attendees` entries can now be `{ email:, name:, partstat: }` hashes (plain email strings still work) — `ATTENDEE` lines gain `CN=` and a settable `PARTSTAT` (`:accepted`/`:declined`/`:tentative`/`:needs_action`/`:delegated`) instead of always `NEEDS-ACTION`.
|
|
13
|
+
- Add `method: :reply`, for building an attendee's `METHOD:REPLY` back to an organizer (omits `RSVP=TRUE`, honors each attendee's `partstat:`).
|
|
14
|
+
- Add `Event#geo` (`GEO:` property), `Event#reminders` (`VALARM` blocks), `Event#busy` (`TRANSP:`), `Event#visibility` (`CLASS:`), `Event#rrule` (raw `RRULE:` recurrence value), and `Event#calendar_name` (`X-WR-CALNAME` on the `VCALENDAR`) — all optional, all emitted by `:ics`/`:ical`/`IcsContent`.
|
|
15
|
+
- Add `method: :counter`/`:decline_counter`, generating `METHOD:COUNTER`/`METHOD:DECLINECOUNTER` for an attendee proposing a new time and an organizer rejecting it, respectively. (Note: `:decline_counter` correctly renders as `METHOD:DECLINECOUNTER` — one word per RFC 5545 — not a literal upcase of the Ruby symbol; fixed via a new `BaseProvider#method_value` used everywhere a `METHOD:`/`method=` value is emitted, including `IcsDownload.headers`.)
|
|
16
|
+
- Add `Event#importance` (`:low`/`:normal`/`:high` → standard `PRIORITY:` + Outlook's `X-MICROSOFT-CDO-IMPORTANCE:`) and `Event#allow_counter` (default `true`; `false` → Outlook's `X-MICROSOFT-DISALLOW-COUNTER:TRUE`, hiding its "Propose New Time" action) and `X-MICROSOFT-CDO-BUSYSTATUS` alongside the existing `TRANSP:` — genuinely real, protocol-level, Outlook-specific properties (confirmed against Microsoft's documented `.ics` extensions), safe to always emit since RFC 5545 requires unrecognized `X-` properties be ignored by other clients.
|
|
17
|
+
- CONFIGURATION.md: rewrite "Guest permissions" — Google/Microsoft's guest-permission toggles are confirmed API-only (no `.ics` property, no parameter on Google's own "add to calendar" render URL either), but the section now documents the real Outlook-specific levers above as the closest addable equivalent. Rewrite "Attendee-proposed reschedules (COUNTER)" now that generation is implemented, with the caveat that mainstream mail clients still don't reliably expose a "propose new time" UI to trigger one from. Add "Tracking RSVPs" (inbound `METHOD:REPLY` webhook vs. provider-API alternative, with the Gmail reliability caveat) for the RSVP-tracking gap, which remains genuinely outbound-only.
|
|
18
|
+
- `Example/calendar_app`: add a working `Meeting`/`MeetingAttendee` persistence example (migration + models + `MeetingsController#create`/`#reschedule`/`#cancel` + `MeetingMailer`) demonstrating the `uid`/`sequence` lifecycle end-to-end, plus an illustrative `EventRepliesController` showing how to parse an inbound `METHOD:REPLY` email. The example app's Gemfile still tracks the published gem — this demo needs 0.2.0, so run it locally against `path: "../.."` until that's released.
|
|
19
|
+
- Add per-attendee `rsvp:` override (`{ email:, name:, partstat:, rsvp: }`) so `RSVP=TRUE` can be suppressed even under `method: :request` — needed for a "registration confirmed" style invite where the recipient is already `partstat: :accepted` and nothing is actually being requested. **Fixed a real bug found while adding it**: the existing symbol/string dual-key lookup pattern (`attendee[:key] || attendee["key"]`) silently discards an explicit `false` value (`false || x` evaluates to `x` in Ruby, not `false`), which would have made `rsvp: false` a no-op; replaced with `BaseProvider#attendee_hash_value`, used for all attendee-hash reads.
|
|
20
|
+
- CONFIGURATION.md: add "Replicating a ticketing-platform confirmation email" — a full worked example (matching a real Luma-style confirmation email byte-for-byte in structure, brand names genericized) covering the `partstat: :accepted, rsvp: false` attendee pattern, the full ActionMailer attachment setup, why `From`/`Reply-To`/`ORGANIZER` can legitimately all differ, and an explicit note that Apple Wallet `.pkpass` passes are an unrelated technology (PassKit, not iCalendar) and out of scope for this gem.
|
|
21
|
+
|
|
3
22
|
## [Released]
|
|
4
23
|
|
|
24
|
+
## [v0.1.7] - 2025-11-09
|
|
25
|
+
|
|
26
|
+
- Upgrading to support Rails 8.1
|
|
27
|
+
- Support gems upgrades
|
|
28
|
+
|
|
29
|
+
## [v0.1.6] - 2024-12-20
|
|
30
|
+
|
|
31
|
+
- Adding Mailer example
|
|
32
|
+
|
|
5
33
|
## [v0.1.5] - 2024-12-19
|
|
6
34
|
|
|
7
35
|
- Should deploy the doc to a GitHub page
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
CalInvite is a Ruby gem for generating calendar invitations (URLs and .ics files) across multiple platforms: Google, Outlook, Outlook 365, Yahoo, Apple iCal, and generic .ics. Ruby >= 3.0.0, Rails 6.0–8.0 compatible, depends on `activesupport`.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bundle install # install dependencies
|
|
13
|
+
rake test # run full test suite (default rake task)
|
|
14
|
+
rake test TEST=test/cal_invite/event_test.rb # run a single test file
|
|
15
|
+
ruby -Itest -Ilib test/cal_invite/event_test.rb # run a single test file directly
|
|
16
|
+
rake rdoc # generate RDoc documentation into doc/
|
|
17
|
+
rake rdoc:clean # remove generated doc/
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Tests are Minitest-based, files live under `test/cal_invite/`, named `*_test.rb`. Coverage is collected via SimpleCov (see `coverage/`).
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
|
|
24
|
+
- **`CalInvite` module** (`lib/cal_invite.rb`) — top-level entry point. Holds a singleton `CalInvite.configuration` (a `Configuration` instance) set via `CalInvite.configure { |c| ... }`. Mixes in `Caching` at the module level for class-level cache helpers.
|
|
25
|
+
|
|
26
|
+
- **`CalInvite::Event`** (`lib/cal_invite/event.rb`) — the central object. Holds all event attributes (title, start/end time, location, url, attendees, timezone, notes, multi-day sessions, all-day flag). `generate_calendar_url(provider)` is the main API: it validates the event, checks the cache (MD5 hash of all attributes + provider as key), and if not cached, resolves `CalInvite::Providers::<CapitalizedProvider>`, instantiates it with `self`, and calls `#generate`. Location and virtual-meeting URL are intentionally separate fields (not merged) so each provider can format them appropriately.
|
|
27
|
+
|
|
28
|
+
- **`CalInvite::Providers`** (`lib/cal_invite/providers.rb`) — namespace with `SUPPORTED_PROVIDERS = %i[google ical outlook yahoo ics office365]`. Provider classes are autoloaded from `lib/cal_invite/providers/*.rb`. To add a new provider: create a class extending `BaseProvider`, implement `#generate`, register it here with `autoload`, and add its symbol to `SUPPORTED_PROVIDERS`.
|
|
29
|
+
|
|
30
|
+
- **`BaseProvider`** (`lib/cal_invite/providers/base_provider.rb`) — abstract base class (note: it's a top-level `class BaseProvider`, not namespaced under `CalInvite::Providers`). Defines the `#generate` contract (must raise `NotImplementedError` if not overridden) plus shared helpers used by subclasses: URL-building (`url_encode`, `format_description`, `format_location`, `format_url`, `format_description_with_url`, `add_optional_params`) and iCalendar property formatting (`attendees_list`, `attendee_emails`, `attendee_hash_value`, `attendee_line`, `organizer_line`, `method_value`, `status_line`, `geo_line`, `transp_line`, `busystatus_line`, `class_line`, `importance_lines`, `disallow_counter_line`, `rrule_line`, `valarm_lines`, `local_wall_time`, `vtimezone_lines`). `attendee_hash_value(attendee, key)` is the correct way to read an attendee-hash field (tries symbol then string key) — don't reintroduce `attendee[:key] || attendee["key"]`, which silently drops explicit `false` values. Each concrete provider (`Google`, `Outlook`, `Office365`, `Yahoo`, `Ical`, `Ics`) builds a provider-specific URL or content string from the `Event` using these helpers.
|
|
31
|
+
|
|
32
|
+
- **`Ics` / `IcsContent` providers** (`ics.rb`, `ics_content.rb`) — generate actual `.ics` file content (RFC 5545) rather than a URL, for direct download flows (see README's `send_data` controller example). `IcsDownload` lives in `ics_content.rb` alongside `IcsContent` (not an alias). All ics-family providers accept a `method:` (`:publish`/`:request`/`:cancel`/`:reply`/`:counter`/`:decline_counter`) passed through `Event#generate_calendar_url`. Use `BaseProvider#method_value` (not `method.to_s.upcase`) when emitting the `METHOD:` line — `:decline_counter` must render as `METHOD:DECLINECOUNTER` (one word) per RFC 5545, unlike its Ruby symbol. `:request` plus `Event#organizer` produces an RFC 5545 meeting request that mail clients render with RSVP actions; `:cancel` (reusing the same `Event#uid`, with `Event#sequence` bumped) produces a real cancellation; `:reply`/`:counter`/`:decline_counter` all omit `RSVP=TRUE` on `ATTENDEE` lines (none of them request a further response). `Event#uid` is stable (auto-generated and memoized per instance, or pass your own) — required so a later `:request`/`:cancel` is recognized as updating the original invite rather than creating a new one. `Event#attendees` entries can be plain email strings or `{ email:, name:, partstat:, rsvp: }` hashes (`partstat:` drives `PARTSTAT=` on the `ATTENDEE` line, default `NEEDS-ACTION`; `rsvp:` overrides the method-derived `RSVP=TRUE`/absent default — needed for e.g. a registration-confirmation invite where the attendee is already `:accepted` and `rsvp: false` suppresses it under `method: :request`). Optional `Event` fields `geo`, `reminders`, `busy`, `visibility`, `rrule`, `calendar_name` map to `GEO:`, `VALARM`, `TRANSP:`, `CLASS:`, `RRULE:`, and `X-WR-CALNAME` respectively; `importance`/`allow_counter` map to Outlook's non-standard `X-MICROSOFT-CDO-IMPORTANCE`/`X-MICROSOFT-DISALLOW-COUNTER` (plus standard `PRIORITY:` and `X-MICROSOFT-CDO-BUSYSTATUS` alongside `TRANSP:`) — safe to always emit since unrecognized `X-` properties are required to be ignored by other clients. See `CONFIGURATION.md`.
|
|
33
|
+
- **Timezones** — `:ics`/`:ical` build a real `VTIMEZONE` (via `CalInvite::IcalTimezone`, backed by `tzinfo`) for any recognized IANA `timezone` other than `'UTC'`, and correctly convert `start_time`/`end_time` (always UTC) to that zone's local wall-clock time for `DTSTART;TZID=...`. `'UTC'` uses plain `Z`-suffixed timestamps with no `VTIMEZONE`.
|
|
34
|
+
|
|
35
|
+
- **`Caching`** (`lib/cal_invite/caching.rb`) — an `ActiveSupport::Concern` mixed into `CalInvite` at the class level. Provides `fetch_from_cache`, `write_to_cache`, `read_from_cache`, `clear_cache!`, `clear_event_cache!`, `clear_provider_cache!`, all keyed under `CalInvite.configuration.cache_prefix`. Works with any `ActiveSupport::Cache::Store`-compatible store, or a custom object responding to `read`/`write`/`delete`. See also `CACHING.md`.
|
|
36
|
+
|
|
37
|
+
- **`Configuration`** (`lib/cal_invite/configuration.rb`) — holds `cache_store`, `cache_prefix` (default `'cal_invite'`), `cache_expires_in` (default 24 hours), `webhook_secret`, `timezone` (default `'UTC'`). `cache_store=` accepts `:memory_store`, `:null_store`, or any object implementing `read`/`write`/`delete`.
|
|
38
|
+
|
|
39
|
+
## Conventions
|
|
40
|
+
|
|
41
|
+
- Always pass times to `Event.new` in UTC; use the `timezone` attribute only to control display/formatting in the generated invite.
|
|
42
|
+
- `location` (physical) and `url` (virtual meeting link) are kept as distinct fields throughout the provider layer — don't conflate them when adding provider logic.
|
|
43
|
+
- All-day events skip `start_time`/`end_time` validation; multi-day events use the separate `multi_day_sessions` array instead of `start_time`/`end_time`.
|
|
44
|
+
- YARD-style doc comments (`@param`, `@return`, `@example`) are used throughout `lib/` and feed the RDoc-generated docs published to GitHub Pages (`.github/workflows/documentation.yml`) — keep them accurate when changing public method signatures.
|
|
45
|
+
- CalInvite is outbound-only: it renders `.ics` content/URLs and has no concept of inbound RSVP replies. It also can't express Google/Microsoft Calendar-API-only concepts like guest permissions (`guestsCanInviteOthers` etc.) since those have no `.ics`/URL representation at all — but it does generate the genuinely protocol-level equivalents that exist: `METHOD:COUNTER`/`DECLINECOUNTER` and Outlook's `X-MICROSOFT-*` extensions (`allow_counter`, `importance`, `busy`). See CONFIGURATION.md's "Tracking RSVPs" and "Guest permissions" sections for the full breakdown of what's real vs. not addable, and why.
|
|
46
|
+
|
|
47
|
+
## Example app (`Example/calendar_app`)
|
|
48
|
+
|
|
49
|
+
Rails 8.1 app demonstrating the gem. Its Gemfile depends on the **published** `cal-invite` gem (never commit it pointing at `path: "../.."`) — when testing example-app changes that rely on unreleased gem code (like the `Meeting` demo below, which needs the still-unreleased 0.2.0), temporarily uncomment the `path: "../.."` line locally, `bundle install`, test, then revert the Gemfile and re-run `bundle install` against rubygems before committing. `Meeting`/`MeetingAttendee` (with a migration) is a working reference implementation of the `uid`/`sequence` persistence pattern CONFIGURATION.md describes — see `app/models/meeting.rb`, `app/controllers/meetings_controller.rb` (create/reschedule/cancel), and `app/controllers/event_replies_controller.rb` (illustrative inbound `METHOD:REPLY` parsing, not wired to a real inbound-email provider). This demo won't actually run against the currently-published gem until 0.2.0 ships.
|