新コンテンツを知らせよう - RSSの追加
2018-02-25
このブログはRailsを使ってフルスクラッチで作られているワケだが、残念な事にRSSフィードの出力をまだ実装していない。しかしRSSフィードを出力すれば定期的にこのブログを見てくれる人も増えるだろうし、諸々のサービスへ連携するのも可能になる。だから今日作るよ。
おそらくRSSフィードを作成するgem、という文言でググるとHit数が少なく選択肢がないように思えるかもしれない。だが実際にはRSSパーサーgemのほとんどはRSSフィードの出力も出来る。当然と言えば当然である。
今回はgemではなく単にxmlとしてBuilder::XmlMarkupで書く。理由はRSS部分がviewとして分離できて気持ちいいから。
1 MVCの実装
2 ルーティングの追加
これだけ。難しいことは特にない。
基本方針
実装をどこから始めてもいいが、まず先に基本方針を決める必要がある。つまりRssを独立したリソースとして扱うか、あるいはRSSに記述するコンテンツであるEntryリソースのViewの一種として扱うかだ。今回は前者で行こう。コンテンツがEntry以外にも作られるかもしれないし、URLとオブジェクトが一致している方が直感だ。ただし実装すべき部分が増える。
VCの実装
特に難しいところはない。FeedControllerとViewを作る。ModelやServiceまで作る必要は無いので今回はこれだけ。
Controller
class FeedController < ApplicationController def show @entries = Entry.where("created_at < ?", 3.hour.ago).order(created_at: :desc).limit(20) # respond_to(&:rss) ワンラインの誘惑に負けてはいけない、可読性を大事に respond_to do |format| format.rss end end end
ところで、たまに○○Controllerを必ず複数系で、かつトップページ相当のメソッドをindexで作る人もいるが自分は今回のFeedのようにユニークで集合体にはならないリソースに関するコントローラーは単数系で書くしindexも使わずshowアクションで書く。
(HomesControllerのindex? HomeリソースがDBに存在してその一覧を出すのか?
やることは単純。フォーマットをrssに指定してviewへrss.builderのようにファイルを作る。最初に書いたがBuilder::XmlMarkupでやっていく、あまり聞かないかもしれないがbuilderはxml用のテンプレートエンジン。
Entryの検索条件に3時間前を指定しているが、これは単に自分が公開後に頻繁な書き直しを行う為の猶予時間なので気にしない。
View
#encoding: UTF-8 cache 'feed_cache_key', expires_in: 1.day do xml.instruct! :xml, version: '1.0' xml.rss('version' => '2.0', 'xmlns:dc' => 'http://purl.org/dc/elements/1.1/') do xml.channel do xml.title Settings.title xml.description Settings.description xml.link Settings.home_url xml.language 'ja-ja' xml.ttl '1440' @entries.each do |entry| xml.item do xml.title entry.title xml.description do xml.cdata! truncate(strip_tags(markdown(entry.body)), omission: '...', length: 500) end xml.pubDate entry.created_at.rfc822 xml.guid entry.full_uri xml.link entry.full_uri end end end end end
注意として、RSSでは日時をRFC822準拠にしなければならないので.rfc822メソッドで変換しておく。
あと、このレンダリングは少し重い。20件のレコードを取って来てMarkdownで記述された記事の本文をHTMLにレンダリングしなければならない。Disk I/OとしてもCPU的にもメモリ的にも割と食う。流石にここはキャッシュしておこう。場合によっては頻繁に呼び出される部分なので一応ね。本来なら全部の記事をMarkdownからHTMLに変換した状態でDBに置いておくほうが高速だがまだやっていない。コンテンツが少なくてアクセス数が低い状態では優先度が無限に低い。
ルーティングの追加
新規のurlを追加してなければならないのでconfig/routing.rbあたりに記述を追加しよう。
get '/feed', to: 'feed#show', format: 'rss'
特に難しいところはなし。注記としてはformat: 'rss'
をつけないとrails4からUnknown Format Errorを起こすようになったので指定が必要。
HTMLにRSSの存在を記述する
さて、このフィードのリンクをページ内に貼っておくだけでもいいのだが、HTMLのHEAD内にRSSが存在していることを明示的に記述することも出来る。
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
こうして明示的に記述することでブラウザの拡張機能でアクセス時に自動でRSSの存在を検出したり、何かしらのボットがRSSを見つけやすくなる。
参考リンク
https://easyramble.com/rails-builder-rss-feed.html
https://qiita.com/klriutsa/items/6662ef75e804c4323228

[155]