旧gaaamiiのブログ

間違ったことを書いている時があります。コメントやTwitter、ブコメなどでご指摘ください

【初心者向け】RubyとSinatra、アンテナサイトの作り方

(2014/12/29)チュートリアル動画を録画しました。こちらもどうぞ。


RubySinatraでアンテナサイト(WebサイトからRSS取得して表示するサイト)を作るチュートリアル的な記事を書いてみることにします。本記事の対象者は「HTMLはわかるけど動的なサイトは作ったことが無い」くらいの人です。

また、いかんせん素人が書いているものなので認識違いや説明不足が見つかるかと思います。コメントやTwitterブコメなどからご指摘くださると助かります。ちなみに、環境はMac OS Xを想定しています。

ソースコードは(初めて)GitHubに置きました。

» gaaamii/sinatra_rss

目次

1. はじめに

2. とりあえずHello,World

  • 準備
  • 実行

3. ビューを作る

  • layout.erb
  • index.erb

4. main.rbでつくった変数をビューに埋め込む

  • views内のファイルとの結びつけ
  • 変数を埋め込む

5. RSSファイルから記事の情報を取り出す

  • サイトのrssファイルを探す
  • gemを足す
  • RSSParserを使う

6. サイトの情報をビューに埋め込む

  • サイトのタイトルを表示
  • サイトのリンクを付ける

7. ループを回して記事を全て表示する

あとがき

関連

1. はじめに

完成品

完成は、こんな感じです。記事の一覧を表示しているだけですね。
f:id:shgam:20130826040827j:plain

Ruby

Rubyが使える環境を用意してください。Mac OS Xなら標準で使えるはずですが、バージョンが古いとか何かしら問題がある場合はぐぐって解決しておいてください。この記事はRuby 2.0.0を想定していますが、Ruby1.9以降ならたぶん問題はありません。

マシンにインストールされているRubyのバージョンを調べるには、ターミナルで以下のコマンドを打ち込んでください。

ruby -v

Sinatra

Sinatraに「環境構築」と呼ばれるような重々しい作業は必要ありません。やることはたった1つ。

  • sinatraというgemをインストールする

これだけです。

ターミナルから

gem install sinatra

でインストールしてください。rootユーザで無い場合(そういう感じのエラーが出たとき)は

sudo gem install sinatra

と入力し、パスワードを答えてください。

フォルダを作る

Rubyが使えることがわかったら、お好みの場所にフォルダを作りましょう。

mkdir RSSApp

このフォルダ内で作業していきます。

2. とりあえずHello,World

Hello,Worldを出すのはもう、一種の通過儀礼ですよね。やっておきましょう。

準備

先ほど作ったRSSAppフォルダの中に、main.rbというファイルを作ります(app.rbでもhogehoge.rbでも大丈夫です)。

その中で、「自分、Sinatra使いたいっす」ってことを書きます。

require 'sinatra'

これでSinatraを使えるようになったので、実際に使ってみます。requireの行の下にこう書いてください。

get '/' do
  "Hello,World."
end

実行

そして、ターミナルからこれを実行します。

ruby main.rb

f:id:shgam:20130823152410j:plain

これで、http://localhost:4567というURLをブラウザから打ち込んでアクセスできるようになります。見ての通りDOMには最低限のタグしか作られておらず、本当にただのHello,Worldです。

f:id:shgam:20130823152758j:plain

もしも今まで動的なWebサイトを作ったことが全く無い人でしたら、ここでいったん喜びましょう。僕は喜びました。

3. ビューを作る

とりあえずmain.rbを実行できたので、次はビューを作ります。ここではテンプレートエンジンとしてERBを使います。テンプレートを使う際はファイル名に注意しましょう。ファイルの構成はこんな感じです。

main.rb
views
  layout.erb
  index.erb

main.rbは任意のファイル名で大丈夫ですが、viewsというフォルダ名・layout.erbというファイル名は決まっています。違う名前で作ってしまうとテンプレートとして使えなくなるので注意です。

layout.erb

layout.erbには複数ページ作る際に共通する部分を記述しておきます。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>RSSアンテナ</title>
  </head>
  <body>
    <h1>RSSアンテナ</h1>
    <%= yield %>
  </body>
</html>

問題ないと思いますが、この行だけ特別です。

<%= yield %>

「ここに他のerbファイルの中身を埋め込んでね」という意味です。

index.erb

そして、index.erbには最終的にRSSから取ってきた情報をリスト表示するための記述をします。が、まだRSSをいじくっていないので、ここではリストのタグだけ書いておきます。ここに書いたものが先ほどのyieldの部分に埋め込まれることになります。

<ul>
  <li>ここにエントリが表示されるよ</li>
</ul>

4. main.rbでつくった変数をビューに埋め込む

そろそろ動的というか、サーバサイドっぽいことをしてみましょう。最終的にやりたいのはRSSから取った記事の情報をリスト表示したいので、取ってきたものをビューに埋め込む方法を知っておかなければなりません。

views内のファイルとの結びつけ

main.rbでルートパスをgetしたときにindex.erbとつなぐには、こう書きます。

get '/' do
  erb :index
end

これでオッケーです。実行すると、先ほどerbファイルに書いた内容が表示されているはずです。

変数を埋め込む

main.rb内でてきとーな文字列を変数に入れます。

get '/' do
  @hello = "こんにちは!じぇじぇじぇ!"
  erb :index
end

先ほどのindex.erbに埋め込みます。

<ul>
  <li>ここにエントリが表示されるよ</li>
  <li><%= @hello %></li>
</ul>

実行してこうなっていればOKです。

f:id:shgam:20130823174930j:plain

さて、これだけできればもうやりたい放題です。やることは基本的に、
main.rbで生成 -> index.erbで表示
だけだとわかれば、だいたいのことができそうな気がしますね。ここらへんでも小さく喜んでおきましょう。

5. RSSファイルから記事の情報を取り出す

さて、次はmain.rbの方でRSSファイルから記事の情報を取り出す作業をします。難しそうですが、gemのおかげでとっても簡単にできます。

サイトのrssファイルを探す

記事をとってきたいサイトのrssファイルを見つけましょう。

見つけるには、サイトのソースを表示します。各ブラウザの開発ツールでもいいですし、「右クリック→ソースを表示」でも良いです。「command + F」などで、"rss"という文字列を検索します。

f:id:shgam:20130823180840j:plain

すると、rssファイルが置かれたURLが見つかるはずです。例えば、はてなブックマークのトップページであればhttp://b.hatena.ne.jp/hotentry.rssです(http://feeds.feedburner.com/hatena/b/hotentryにリダイレクトされますが、どちらでもオッケーです)。

以下ではこのURLを使います。
http://b.hatena.ne.jp/hotentry.rss

gemを足す

urlをもとにrssファイルを扱うにはrssというgemが必要ですので、これをrequireする行を書き足しておきましょう。

require 'sinatra'
require 'rss'
...

RSSParserを使う

get '/' do
  @rss = RSS::Parser.parse("http://b.hatena.ne.jp/hotentry.rss")
  erb :index
end

細かいことはおいといて、上でやっているのはURLからrssを取ってきたという感じです。すっごい簡単ですね。それを@rssというインスタンス変数に入れてあります。

6. サイトの情報をビューに埋め込む

サイトのタイトルを表示

情報をちゃんと取れたか確認する意味で、まずはサイトのタイトルを表示してみましょう。

<ul>
  <li><%= @rss.channel.title %></li>
</ul>

はてなブックマーク - 人気エントリー」と表示されていればオッケーです。

サイトのリンクを付ける

リンクが無ければアンテナサイトにならないのでリンクを付けます。

<li><a href="<%= @rss.channel.link %>"><%= @rss.channel.title %></a></li>

ここまでで、サイトの情報が取れていること・それを表示できることがわかりました。

7. ループを回して記事を全て表示する

では、この情報から全ての記事を表示します。一つ一つの記事を表示するには、ビュー(index.erb)の方でループを回してあげます。

記事の情報は@rss.itemsに配列の形で入っているので、これらは.eachで取れます。ここでentryに入れているのは、一記事分の情報です。

(2014/6/16 追記)aタグの閉じタグを忘れていたので追記しました。

<ul>
<% @rss.items.each do |entry| %>
  <li><a href="<%= entry.link %>"><%= entry.title %></a></li>
<% end %>
</ul>

できました。これでentryが取れなくなるまでリストにリンクと記事タイトルを埋め込んで表示してくれます。

f:id:shgam:20130826040827j:plain


ここまでの処理を、フィード元を増やしてやればアンテナサイトができますよね。
チュートリアルは以上です。

あとがき

正直、自分で書いててRSS::Parserのやっていることがぜんぜん分かっていないことに気付きました。あと、はてなブックマーク数を取る方法も実はわかっていません名前空間がどうのこうのという問題らしいです。

結局この記事はRubySinatraの解説というより、「とりあえずフィード表示できたやつがとりあえずフィード表示したい奴に向けて書いた記事」になりました。それでも初心者には何かしらの役には立つと思います。補足は随時足していくつもりですが、詳しいこと分かる人はこの記事にがんがんコメントやツッコミくださいお願いします。

関連

たのしいRuby

rssの処理はこちらに書いてありました。「第3版」なのに注意。「第4版」ではrssについて触れられていません。

Sinatra: README(Japanese)

わざわざチュートリアル書いといてアレですけど、Sinatraの使い方は僕ななんかの記事読むよりこちらを読んだ方が良いです。

» Sinatra: README (Japanese)