duyojiぶろぐ

技術系ときどき日常系

Sinatra,hamlでシンプルなTwitterクライアントを作る

Sinatraを使ってホームタイムラインの表示、投稿が出来るTwitterクライアントを作る。
テンプレートエンジンはhamlを使用する。rubyのバージョンは1.9.2で話を進める。
ソースコードはgithubにアップしてるのでそっちのほうも参考にしながらこの記事を読むと分かりやすいかもしれない。
参考にしたサイトは記事の最後の方に書いておく。

準備

oauth認証とtwitterAPIを使うのでそれぞれのライブラリ、使用するフレームワーク(sinatra)をインストールする。

gem install sinatra
gem install oauth 
gem install twitter

app.rbの中身

configure do
	use Rack::Session::Cookie, :secret => Digest::SHA1.hexdigest(rand.to_s)
	KEY = "Consumer key"
	SECRET = "Consumer secret"
end

configure do ~ endはどの環境でも起動時に1回だけ読み込まれるところ。
ここで使うアプリを登録した際に発行されたConsumer key,Consumer secretを記述する。

def configure_twitter_token
  Twitter.configure do |config|
    config.consumer_key = KEY
    config.consumer_secret = SECRET
    config.oauth_token = session[:access_token]
    config.oauth_token_secret = session[:access_token_secret]
  end
end

before do
	@title = "Simple Twitter Sinatra"
	if session[:access_token]		
		configure_twitter_token
		@twitter = Twitter::Client.new
	else
		@twitter = nil
	end
end

Sinatraのサイトの記事をそのまま引用すると、
「beforeフィルタはリクエストされたコンテキストを実行する前に評価され、 リクエストとレスポンスを変更することができます。フィルタ内でセットされた インスタンス変数はルーティングとテンプレートで使用できます。」と書かれている。

ここではsession[:access_token]に値が入っている場合はconfigure_twitter_tokenメソッドでTwitterのクライアントの設定をして、@twitterTwitterAPIを使えるようにするためにインスタンスを作っている。

def base_url
	default_port = (request.scheme == "http") ? 80 : 443
	port = (request.port == default_port) ? "" : ":#{request.port.to_s}"	
	return  "#{request.scheme}://#{request.host}#{port}"
end

def oauth_consumer
	return  OAuth::Consumer.new(KEY, SECRET, :site => "http://twitter.com")
end

get '/request_token' do
	callback_url = "#{base_url}/access_token"
	request_token = oauth_consumer.get_request_token( :oauth_callback => callback_url )
	session[:request_token] = request_token.token
	session[:request_token_secret] = request_token.secret
	redirect request_token.authorize_url
end

ここでは/request_tokenにURLが飛んだ時に変数callback_urlにアプリを許可した後に飛ぶURLを代入している。
base_urlメソッドの処理は完全に理解はしていないが、requestはsinatraインスタンスだと思われる。
githubにアップしているソースコードをそのまま
起動した場合、request.scheme=="http",request.host=="localhost",port==4567と表示された。

「redirect request_token.authorize_url」で認証画面へ飛ばしている。

get '/access_token' do
	request_token = OAuth::RequestToken.new(oauth_consumer, session[:request_token], session[:request_token_secret])
	begin
		@access_token = request_token.get_access_token(
				{},
				:oauth_token => params[:oauth_token],
				:oauth_verifier => params[:oauth_verifier])
	rescue OAuth::Unauthorized => @exception
		return erb %{ oauth failed: <%=h @exception.message %> }
	end
	session[:access_token] = @access_token.token
	session[:access_token_secret] = @access_token.secret
	redirect '/'
end

ここは先ほど認証画面でアプリを許可したあとにコールバックに指定したURLである。
ここでは色々処理をして最後に'/'にリダイレクトする。
ここでどんな処理をしているかはきちんと理解出来ていないので以下に書いたSinatra と OAuth を使って Twitter のタイムラインを取得してみたを参考にして欲しい。

get '/' do
	if @twitter
		haml :timeline
	else
		haml :login
	end
end

ここではbeforeフィルタで処理をした@twitterに値が入っているか入っていないかを区別して表示するテンプレートを切り替えている。
sessionがあればタイムラインを、なければログイン画面を表示する。

post '/' do
	@twitter.update(params[:tweet]);
	redirect '/'
end

timeline.hamlのフォーム処理をここで行っている。textareaに書いたものを投稿する。