Nwht0xn1

RailsでiCalendar形式で予定を公開するCreated on 2016-06-27 by r7kamura

漫画の新刊管理するWebサービス作ってて、自分の持ってる漫画の新刊カレンダーをiCalendar形式で吐き出すのに使った。WikiHubにも予定を管理する何らかの機能を入れることになるかもしれないのでメモ。

Content-Type: text/calendar

iCalendar形式で予定を公開したければ、Content-Typeヘッダにtext/calendarを指定しながら、iCalendar形式の文字列を本文に含むレスポンスを返せば良い。GoogleCalendarに登録するには、そのようなレスポンスを返すようなエンドポイントのURLを登録する。

icalendar gem

iCalendar形式の文字列をRubyで生成するには、ぱっと調べた感じ、ここ数年間 icalendar というGemが多く利用されている。

X-WR-CALNAME;VALUE=TEXT

独自プロパティとして X-WR-CALNAME;VALUE=TEXT:... というプロパティを追加すると、iCal.appなどでカレンダーのタイトルとして認識される。

開発時の確認方法

開発環境では、Content-Type: text/calendar を返すようなエンドポイントにアクセスすると、iCalendar形式のファイルがダウンロードされる。拡張子が *.ics のファイルは、例えばOS XであればCalendar.appで開いて動作を確認できる。これで終日イベントにして実装したつもりが時刻指定になってしまっているとか色々わかる。

終日イベント

終日イベントを表現するには、dtstartの値が日付表現 (時刻を含まない表現) になっている必要がある。icalendar gemでこれを表現するには、以下のURLを参考にすると良い。1日だけの終日イベントの場合、dtendの値を省略するとCalendar.appには上手く認識された。

サンプルコード

最近利用したコードの例

class IcalendarsController < ApplicationController
  def show
    user = find_user_from_request!
    products = user.subscribed_products
    calendar = ::Icalendar::Calendar.new
    calendar.append_custom_property("X-WR-CALNAME;VALUE=TEXT", "r7kamura calendar")
    products.each do |product|
      event = ::Icalendar::Event.new
      event.created = product.created_at
      event.description = product.name
      event.dtstart = ::Icalendar::Values::Date.new(product.released_at.to_date)
      event.dtstamp = product.created_at
      event.last_modified = product.created_at
      event.summary = product.name
      event.uid = product.id.to_s
      event.url = product_url(product_id: product.id)
      calendar.add_event(event)
    end
    calendar.publish
    headers["Content-Type"] = "text/calendar; charset=UTF-8"
    render text: calendar.to_ical
  end
end