はじめに
みなさん、こんばんは。まどぎわです(・∀・)
rubyの標準ライブラリにRSS用のライブラリがあることを最近知り、railsと標準ライブラリを使ってRSSリーダー的なものを作ってみたので、作り方とかをメモしておきます✍
作るもの
はてなブログのRSSフィードのエンドポイントを登録したら、そこからRSSをパースして表示出来るようなアプリを作っていきます👀
こんな感じのものをイメージしてもらえれば!
使うもの
作り方
モデルを作る
とりあえずモデルを作ります。作るものを下記の2つです。
- Feed.rb
- Entry.rb
Feed.rb
にはRSSフィードのタイトルとエンドポイントのURLを登録します。Entry.rb
には、フィードから取得したエントリーを登録します。
schemeはこんな感じです。
create_table "entries", force: :cascade do |t| t.bigint "feed_id" t.string "title" t.string "link" t.text "description" t.datetime "published_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["feed_id"], name: "index_entries_on_feed_id" end create_table "feeds", force: :cascade do |t| t.string "title", null: false t.string "endpoint", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end
RSSを読み込んでParseする
それでは、RSSを読み込んでパースする部分は結構簡単で、ruby標準のrssライブラリをrequire 'rss'
で読み、Net::HTTP.get(URI.parse(endpoint))
でxmlドキュメントを取得して、RSS::Parser.parse
を使ってParseします。
私は、Feedモデルにparsed_xml
を定義してParseしたxmlを取得出来るようにしてみました👀
class Feed < ApplicationRecord require 'rss' has_many :entries def parsed_xml xml = Net::HTTP.get(URI.parse(endpoint)) RSS::Parser.parse(xml) end end
エントリーを取得して保存する
その後は、Parseしたxmlのitems
に記事の一覧が入っているので、下記のようなEntryCreater
クラスを作成して、画面登録時に記事一覧を取得して登録するようにしました🙌
class FeedsController < ApplicationController def new @feed = Feed.new end def create @feed = Feed.new(feed_params) if @feed.save Feed::EntryCreater.new(@feed).execute redirect_to feed_path(@feed) else render :new end end private def feed_params params.require(:feed).permit(:title, :endpoint) end end
class Feed::EntryCreater attr_reader :feed def initialize(feed) @feed = feed end def execute Entry.where(feed: feed).delete_all feed.parsed_xml.items.map do |item| Entry.create( feed: feed, title: item.title, description: strip_tags(item.description).truncate(300), published_at: item.pubDate, link: item.link ) end end private def strip_tags(text) ActionController::Base.helpers.strip_tags text end end
保存したエントリーを表示する
保存したエントリーを表示するのは普通に表示してあげればOKです🙆♂️
class FeedsController < ApplicationController def show @feed = Feed.includes(:entries).find(params[:id]) end end
<div class="feed-show"> <h1 class="title"><%= @feed.title %></h1> <div class="entries"> <%= render partial: 'entry_collection', collection: @feed.entries, as: 'entry' %> </div> </div>
<div class="card"> <header class="card-header"> <p class="card-header-title"><%= entry.title %></p> </header> <div class="card-content"> <div class="content"> <%= entry.description %> <%= link_to 'サイトで読む', entry.link %> </div> </div> <footer class="card-footer"> <p class="card-footer-item"> <%= link_to entry.feed.title, feed_path(entry.feed) %> </p> <p class="card-footer-item"> 公開日: <%= l(entry.published_at, format: :long) %> </p> </footer> </div>
おわりに
rubyの標準ライブラリを使うとRSSを簡単にParseしてRSSリーダー的なものがすぐ作れるんですねー。
他にも標準ライブラリは結構あるので、いろいろ見てみようかと思いました🙇♂️