RailsでOAuthとRubytterを使ってTwitterクライアントを作る
一年ほど前にこんな記事を書きました。情報が古くなってしまったのと、僕が新規にTwitterマッシュアップアプリを今作ってるということで、書き直すことにしました。
動作確認環境
Mac OS X 10.6.6
ruby 1.9.2p136
Rails 3.0.3
完成イメージ図

TwitterをOAuth経由で認証し、タイムラインを表示する簡単なものです。
想定読者
Rubyはある程度書ける。
Rails3については分からない。(Rails2、または他のMVCフレームワークを使用したことがある。)
OAuthの仕組みもよく分からない。
RubyとRailsはインストールされてる前提で話を進めます。インストールについては他の記事をご参照ください。また、Rubyについての解説もしません。Rails3については適当に説明を入れてあります。テストは書いてありますが、Twitterマッシュアップアプリを作るということに焦点を当てるため、省きます。また、コードはDiff風に書いてあります。
プロジェクトの作成
まずはrails newコマンドでプロジェクトの作成。
$ rails new rails3-twitter --skip-active-record --skip-test-unit
create
create README
create Rakefile
create config.ru
create .gitignore
create Gemfile
create app
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create app/mailers
create app/models
create app/views/layouts/application.html.erb
create config
create config/routes.rb
create config/application.rb
create config/environment.rb
create config/environments
create config/environments/development.rb
create config/environments/production.rb
create config/environments/test.rb
create config/initializers
create config/initializers/backtrace_silencers.rb
create config/initializers/inflections.rb
create config/initializers/mime_types.rb
create config/initializers/secret_token.rb
create config/initializers/session_store.rb
create config/locales
create config/locales/en.yml
create config/boot.rb
create db
create db/seeds.rb
create doc
create doc/README_FOR_APP
create lib
create lib/tasks
create lib/tasks/.gitkeep
create log
create log/server.log
create log/production.log
create log/development.log
create log/test.log
create public
create public/404.html
create public/422.html
create public/500.html
create public/favicon.ico
create public/index.html
create public/robots.txt
create public/images
create public/images/rails.png
create public/stylesheets
create public/stylesheets/.gitkeep
create public/javascripts
create public/javascripts/application.js
create public/javascripts/controls.js
create public/javascripts/dragdrop.js
create public/javascripts/effects.js
create public/javascripts/prototype.js
create public/javascripts/rails.js
create script
create script/rails
create tmp
create tmp/sessions
create tmp/sockets
create tmp/cache
create tmp/pids
create vendor/plugins
create vendor/plugins/.gitkeep
DBを使わないのでActiveRecord(という名前のORM)をスキップします。また、僕はテストフレームワークにTest::UnitではなくRSpecを使用しているためTest::Unitのスキップします。ここは適当に読み替えてください。その他のオプションは「$ rails new –help」で見ることが出来ます。
RubytterをGemfileに記述しインストール
Rails3ではBundleという仕組みで使用するGemを管理します。使用するGemはGemfileに書く必要があります。今回はRubytterというTwitterライブラリを使用するので、その指定をGemfileに記述します。また、上記した通り僕はRSpecを使用しているので、開発時とテスト時にRSpecを使用するという記述もしています。
Gemfile
source 'http://rubygems.org' gem 'rails', '3.0.3' +gem 'rubytter' +group :development, :test do + gem 'rspec-rails', '>= 2.3.0' +end
Gemfileに記述したGemはプロジェクトルートで「$ bundle install」というコマンドを実行することでインストールします。アプリケーションを動かすのに足りないものがあれば、全てまとめてインストールされます。
$ bundle install Fetching source index for http://rubygems.org/ Using rake (0.8.7) Using abstract (1.0.0) Using activesupport (3.0.3) Using builder (2.1.2) Using i18n (0.5.0) Using activemodel (3.0.3) Using erubis (2.6.6) Using rack (1.2.1) Using rack-mount (0.6.13) Using rack-test (0.5.7) Using tzinfo (0.3.24) Using actionpack (3.0.3) Using mime-types (1.16) Using polyglot (0.3.1) Using treetop (1.4.9) Using mail (2.2.14) Using actionmailer (3.0.3) Using arel (2.0.7) Using activerecord (3.0.3) Using activeresource (3.0.3) Using bundler (1.0.7) Using diff-lcs (1.1.2) Using json (1.4.6) Using oauth (0.4.4) Using thor (0.14.6) Using railties (3.0.3) Using rails (3.0.3) Using rspec-core (2.4.0) Using rspec-expectations (2.4.0) Using rspec-mocks (2.4.0) Using rspec (2.4.0) Using rspec-rails (2.4.1) Using rubytter (1.4.1) Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
コントローラとルーティングを作成する
コントローラは「$ rails generate controller」で作成出来ます。indexコントローラと、その下にindex, oauth, callbackのアクションを作成します。アクションはそれぞれ、認証ボタンの表示/ツイートの表示、認証ボタンを押した時にTwitterに転送する、Twitterから認証された時の後処理、に使用します。
$ rails generate controller index index oauth callback
create app/controllers/index_controller.rb
route get "index/callback"
route get "index/oauth"
route get "index/index"
invoke erb
create app/views/index
create app/views/index/index.html.erb
create app/views/index/oauth.html.erb
create app/views/index/callback.html.erb
invoke rspec
create spec/controllers/index_controller_spec.rb
create spec/views/index
create spec/views/index/index.html.erb_spec.rb
create spec/views/index/oauth.html.erb_spec.rb
create spec/views/index/callback.html.erb_spec.rb
invoke helper
create app/helpers/index_helper.rb
invoke rspec
create spec/helpers/index_helper_spec.rb
ルーティングを書き換えて、”/”, “/oauth”, “/callback”というURLでアクションにアクセス出来るようにします。
config/routes.rb
Rails3Twitter::Application.routes.draw do - get "index/index" + root to: "index#index", as: :index - get "index/oauth" + get "/oauth" => "index#oauth", as: :oauth - get "index/callback" + get "/callback" => "index#callback", as: :callback
Twitterへのアプリケーション登録
大事なことを忘れていました。OAuth経由でTwitterにアクセスするためには、アプリケーション登録をしConsumer KeyとConsumer Secretを取得する必要があります。
http://twitter.com/oauth_clients

今回作成するのはブラウザアプリケーションのため、”アプリケーションの種類”はブラウザアプリケーションをチェックします。Webサイトは公開予定のURLか、またはhttp://example.com/と入れておきましょう。コールバックURLの指定もありますが、これは認証時に上書きすることが出来るので、適当なものでも大丈夫です。
Consumerを取得するラッパーメソッドを作成
ApplicationControllerにConsumerのインスタンスを取得するラッパーメソッドを作成します。’consumer key’, ‘consumer secret’と書かれた部分は自分で取得したものに置き換えてください。
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
+
+ protected
+ def self.consumer
+ OAuth::Consumer.new(
+ 'consumer key',
+ 'consumer secret',
+ {site: "http://twitter.com"}
+ )
+ end
+
end
認証ボタンを作成
Twitterの認証に飛ぶためのボタンを作成します。
app/views/index/index.html.erb
-<h1>Index#index</h1> -<p>Find me in app/views/index/index.html.erb</p> +<% form_tag :oauth, method: :get do |f| %> + <%= submit_tag '認証する' %> +<% end %>
また、プロジェクト作成時に作成されたWelcomeページは要らないので削除します。
$ rm public/index.html
ひとまずここでサーバを動かしてみましょう。「$ rails server」コマンドで起動出来ます。
$ rails server
http://0.0.0.0:3000/にアクセスして確認してみます。
そっけないながらもボタンが表示されました。
OAuthアクションを作成
認証ボタンを押した時にTwitterに転送するためのoauthアクションを作成します。
app/controllers/index_controller.rb
def oauth
+ callback_url = "http://#{request.host_with_port}/callback"
+ request_token = self.class.consumer.get_request_token(oauth_callback: callback_url)
+
+ session[:request_token] = {
+ token: request_token.token,
+ secret: request_token.secret
+ }
+
+ redirect_to request_token.authorize_url
end
Twitterから未認可のrequest tokenを発行して貰うためにOAuth::Consumerのインスタンスからget_request_tokenメソッドを呼びます。これでOAuth::RequestTokenのインスタンスを取得出来ます。また、この時にcallback先としてcallbackアクションのURLを指定します。発行して貰ったrequest tokenは後からまた使うのでtokenとsecretをセッションに保存しておきます。認証するためのURLはOAuth::RequestTokenのauthorize_urlメソッドで取得することが出来るので、そのURLにリダイレクトさせます。
Callbackアクションを作成
Twitterから認証された時の後処理するためのcallbackアクションを作成します。
def callback
+ if params[:denied]
+ session.delete :oauth
+ else
+ request_token = OAuth::RequestToken.new(
+ self.class.consumer,
+ session[:request_token][:token],
+ session[:request_token][:secret]
+ )
+
+ access_token = request_token.get_access_token(
+ {},
+ oauth_token: params[:oauth_token],
+ oauth_verifier: params[:oauth_verifier]
+ )
+
+ session[:oauth] = {
+ token: access_token.token,
+ secret: access_token.secret
+ }
+ end
+
+ session.delete :request_token
+
+ redirect_to :index
end
まず、認証拒否された時です。認証拒否された時はdeniedパラメータが送られてきます。セッションに前回以前に保存されたoauth tokenがあった場合削除します。indexにリダイレクトをかけます。
次に、認証された時です。セッションに保存しておいたrequest tokenとrequest secretを復元してOAuth::RequestTokenのインスタンスを作成します。oauth_tokenとoauth_verifierパラメータが送られてくるので、OAuth::RequestTokenのget_access_tokenメソッドに渡し、access token(oauth token)と交換します。これでOAuth::AccessTokenのインスタンスが取得出来ます。request tokenは用済みなので、セッションから削除し、代わりにaccess tokenとaccess secretをセッションに保存します。これ以降はaccess tokenを使ってTwitterにアクセスすることが出来ます。
OAuthで認証する
この時点で、OAuth経由でTwitterに認証してもらうことが出来るようになりました。試してみましょう。
callbackアクションを経由して再びindexページへ。

タイムラインを表示する
認証まで出来ました。次は、indexページで認証されてる場合にフレンドタイムラインを表示するようにしましょう。
app/controllers/index_controller.rb
def index + return unless session[:oauth] + + access_token = OAuth::AccessToken.new( + self.class.consumer, + session[:oauth][:token], + session[:oauth][:secret] + ) + + rubytter = OAuthRubytter.new(access_token) + + begin + @tweets = rubytter.friends_timeline + rescue Rubytter::APIError + session.delete :oauth + end end
認証されいない場合は、何もせずテンプレートを表示します。
認証されていた場合は、セッションに保存していたaccess tokenを取り出してOAuth::AccessTokenのインスタンスを作成します。それを引数にOAuthRubytterのインスタンスを作成します。このインスタンスからツイートしたりタイムラインを取得したり出来ます。フレンドタイムラインの取得はfriends_timelineメソッドです。
ユーザーがaccess tokenを無効化したりアクセスを拒否をした場合はRubytter::APIError例外が投げられます。その場合はセッションのaccess tokenを削除しています。
app/views/index/index.html.erb
(インデントが変わりdiffが見にくいので全体のコードを記します。)
<% unless session[:oauth] %>
<% form_tag :oauth, method: :get do |f| %>
<%= submit_tag '認証する' %>
<% end %>
<% else %>
<div id="friends_timeline">
<dl>
<% @tweets.each do |t| %>
<dt><%= image_tag t.user.profile_image_url, size: '40x40' %></dt>
<dd><%= t.user.name %></dd>
<dd><%= t.text %></dd>
<% end %>
</dl>
</div>
<% end %>
認証されてない場合は認証ボタンを表示、認証済みの場合はタイムラインを表示します。
さて、ブラウザに戻りリロードしてみましょう。タイムラインが表示されました。
まとめ
ほら、簡単でしょ?RailsフレームワークとRubytterライブラリのおかげで少ないコードで認証してタイムラインの表示まですることが出来ます。後は、各々思い描いているTwitterマッシュアップアプリケーショを作成するだけです!
ソースコード
上記ソースコードは、テストコード含め全てGithubに上げてあります。
ライセンスはWTFPLです。
ご自由にお使いください。
mitukiii/rails3-twitter - GitHub
参考リンク
RailsでTwitterのOAuthを試す | おいぬま日報
RailsでのTwitterマッシュアップアプリを書くにあたって、こちらの記事を参考にさせて頂きました。
System.Exit – Rubytter
TwitterのRubyライブラリRubytterの公式ページ/作者様ブログ。
Ruby OAuth GEM
OAuthのRubyライブラリOAuthの公式ページ。
合わせて読みたい
ゼロから学ぶOAuth:第1回 OAuthとは?―OAuthの概念とOAuthでできること
OAuthの概念について。読んでも最初はよく分からないと思うので手を動かして作ってみるのが良いと思います。
Ruby on Rails3を使ってアプリ作ってみたメモ
僕がRails3を初めて使った時につまづいたところ/分からなかった事のメモと、Rails3についての情報源。


2 Comments
参考にして作ってみました!
認証ボタンを作成するところで、
app/views/index/index.html.erb
-Index#index
-Find me in app/views/index/index.html.erb
+
+
+
のところ、
+
となっていたのでボタンが出ず、ハマってしまいました。
+
と=を入れるとちゃんと動き、ボタンが表示されました。
良い記事をありがとうございました!!
あっ、タグになってコードが表示されていない……。
% form_tag :oauth, method: :get do |f| %
の、%のあとの=が抜けていた ということです。
それと、
application_controller.rbなのですが、
{site:”http://twitter.com”}だとJSONのパーサーエラーになってしまったのですが、
{site:”http://api.twitter.com”}にするとうまくいきました。
とにかく、良い記事をありがとうございました。
One Trackback/Pingback
[...] てはこの記事が参考になると思います。 Rails3でRubytterを使ってTwitterマッシュアップアプリを作る [...]
Post a Comment