Login
Immutable PageDiscussionInfoAttachments
Diff for "alstamber/Egofav"

MMA
Differences between revisions 4 and 5
Revision 4 as of 2012-12-10 02:22:21
Size: 9442
Editor: alstamber
Comment:
Revision 5 as of 2012-12-10 02:25:09
Size: 9665
Editor: alstamber
Comment:
Deletions are marked like this. Additions are marked like this.
Line 133: Line 133:
  * 後ろについている!マークには特に文法上の意味は無いそうだが、一部の関数型言語にありがちな破壊的な操作を行うメソッドに対して慣例的に付けられるようだ

なにこれ

  • もとから自分の名前の入ったツイートを自動的にふぁぼるスクリプトがあれば便利だなあ(?)と思っていた
  • いつもどおりPythonで書こうと思ったけど日本語周りが糞過ぎてヤル気が失せる
  • ならついでにRubyのお勉強を兼ねてRubyでスクリプト書いてみようかな

Rubyとか全然わからない件

  • こうやればHello, Worldできるのは知ってる

   1 puts "Hello, World"
  • ブロックなにそれ美味しいの?

とりあえずOAuthしないとね

  • OAuthの処理を一から書くなどというドMなことしたくないし、余計なバグを生むだけだし、そもそも車輪の再生産もいいところなのでライブラリを探す
  • exampleに挙がっているソースコードを解読

   1 @consumer=OAuth::Consumer.new( "key","secret", {
   2     :site=>"https://agree2"
   3 })
  • 先頭の@はなんだ
    • perlで言えば配列だけど……
    • インスタンス変数らしい
  • ::とは
    • 基本的には.と同じで、あるクラスorモジュールの中に入っているものを参照する
      • 今回の場合OAuthモジュールの中のConsumerクラスを参照している
    • 大文字で始まるメソッドを引数なしで呼び出す場合は::だとエラーになるらしい
      • Rubyでは大文字で始まるトークンを定数としてみなすため
  • クラスとモジュールは何が違う
    • クラスはインスタンスオブジェクトを生成するためのひな形として働く
      • クラスがもつnewというメソッドを呼び出すとそのクラスに対応するインスタンスオブジェクトが生成される
    • モジュールからはインスタンスオブジェクトを生成することはできない
      • クラスは継承ができるが、モジュールは継承ができない
      • モジュールにメソッドを定義しておいて、それを別のクラスに挿木のように読み込んでくることができる
    • 今回使うライブラリのOAuthモジュールは、単に複数のクラスを一つにまとめる目的で用意されているようだ
  • {:site〜}の部分の意味とは
    • rubyでは次のように書くとハッシュを作ることができる

   1 {:symbol => value,
   2  :symbol => value,
   3  ...
   4 }
  • :symbolとは
    • :hogeとかくとhogeがsymbolというものになるそうで
    • ハッシュのキーは普通の文字列でもいいのだけど、symbolを使うほうがrubyでは主流らしい
  • つまりハッシュを引数に与えているってことですね
  • これとは別に次のようなメソッドもあるらしい

   1 OAuth::AccessToken.new(consumer, ACCESS_TOKEN, ACCESS_SECRET)
  • consumerのところには先程のConsumerクラスのインスタンスを突っ込めば良い
  • ACCESS_TOKENとACCESS_SECRETにはそれぞれdev.twitter.comで手に入れられるトークンを突っ込めば良い
  • こうして得られたAccessTokenのインスタンスを使ってTwitterの認証を行う

ふぁぼスクリプトの挙動を考える

  • Userstreamに接続して自分のタイムラインに流れてくるツイートを読み込んでくる
  • ツイートに「こはく」が含まれていればそれをふぁぼる

Userstreamへの接続

   1 uri = URI.parse("https://userstream.twitter.com/2/user.json")
   2 https = Net::HTTP.new(uri.host, uri.port)
   3 https.use_ssl = true
   4 https.verify_mode = OpenSSL::SSL::VERIFY_NONE
   5 
   6 https.start do |https|
   7     #do something
   8 end
  • 接続したいURLをURI.parseを使ってパースしてURIクラスのインスタンスにする
  • それを使ってHTTPクラスのインスタンスを生成する
  • HTTPS接続のためのもろもろの設定をする(SSL接続するとか証明書はどうとか)
  • startメソッドを呼び出すと通信が開始される
    • startメソッドの後ろについてるdo〜endとは
      • こういうものがついているメソッドをブロック付きメソッドという
        • do〜endをブロックというため
  • ブロック付きメソッドは典型的には次のように記述する

   1 method do |param|
   2  #do something
   3 end
  • またmethodは次のようになっている

   1 def method
   2  #do something
   3  yield hoge
   4 end
  • Rubyではメソッドをdef〜endで定義する
    • メソッドの定義中でyield hoge(hogeは変数)と記述するとdo〜endのブロックが実行される
    • このとき変数hogeはメソッド呼び出しに記述した|param|のparamという名前でブロックの中で使用出来る
  • 例えば

   1 def hoge
   2  yield "test"
   3 end
   4 
   5 hoge do |foo|
   6  puts foo
   7 end
  • 上のプログラムを実行すればtestが出力される
  • いわば高級なイテレータのようなものであろう
  • ふと思ったんだけど、レキシカルクロージャみたいなもんだよね、これ
  • https接続が確立できたところでuserstreamを取り込んでいく
  • TwitterのDeveloper向けサイトによれば、GETメソッドでタイムラインは取ってくることができるらしい
  • OAuth認証を行ってGETメソッドでテキストを取得するには次のように記述すれば良いようだ

   1 request = Net::HTTP::Get.new(uri.request_uri)
   2 request.oauth!(https, access_token.consumer, access_token)
   3 https.request(request) do |response|
   4  #do something
   5 end
  • まずGETメソッドでリクエストを発行するためにGetクラスのインスタンスを生成する
  • 次にoauth!メソッドを呼び出している
    • これの実体はNet::HTTPGenericRequestに定義されている
    • このクラスは元々Rubyに備わっているクラスであるが、実際にはoauth!というメソッドは今回使用しているOAuthライブラリが勝手に追加定義しているようである
      • Rubyでは同名のクラスを2回定義するとクラスの追加定義という意味になる
    • Net::HTTP::GetクラスはNet::HTTPGenericRequestのサブクラス
      • Net::HTTPGenericRequestは抽象クラスで、これを直接インスタンス化することはないらしい
    • このメソッドを呼び出すことでOAuth認証してGETメソッドのリクエストを発行する手はずが整う
    • 後ろについている!マークには特に文法上の意味は無いそうだが、一部の関数型言語にありがちな破壊的な操作を行うメソッドに対して慣例的に付けられるようだ
  • 最後にrequestメソッドでリクエストを発行する
    • このメソッドはブロック付きメソッドで、リクエストの応答はブロックのパラメータの形で手に入る
  • 応答の本体部分を読み出せば、JSON形式で記述されたタイムラインが手に入る
  • RubyではJSON形式で書かれたテキストをハッシュにパースするJSON::parseメソッドが用意されている

もう少し補足

   1 begin
   2  #something
   3 rescue => e
   4  #something
   5 end
  • Rubyのコードを読んでいるとよく見かける
  • 例外処理っぽい
  • beginとrescueの間に書かれている処理を行なっている時に例外が発生するとrescue以下に移動する
    • rescue => eと書いとくと例外の内容がeに格納される

    • rescue hogehoge => eと書けば、hogehogeに示されている例外が発生した時だけrescue以下が実行される

   1 raise "hogehoge" unless fugafuga
  • こちらも例外処理
  • unless以下に書かれている条件が成立しなかった時"hogehoge"をメッセージとするRuntimeErrorという例外が発生する

  • hash['hoge']と記述すれば、hashというハッシュのキーhogeの値を参照できる
    • 先述の通りhash[:hoge]と書くほうがいいかもしれない
  • 今回使用しているOAuthのライブラリはAccessTokenクラスに次のようなインスタンスメソッドを持っている

   1 OAuth::AccessToken.post(path, body='', headers={})
  • これはOAuth認証を介してPOSTメソッドでリクエストを発行するメソッドであるようだ
  • pathはリクエスト先、bodyとheadersはそれぞれリクエストで送信されるデータの本体とヘッダにあたる
    • 本体はただのStringで、headersはハッシュになっていることがわかる
  • Twitter APIでは「ふぁぼる」動作はhttps://api.twitter.com/1/favorites/create/{id}.jsonに対するPOSTメソッドで実現されるのでこのメソッドが必要になる
    • idにはそのツイートのIDが入る
  • Rubyでは#{hoge}と文字列中で書くと、hogeの評価結果が文字列中に展開される
    • ただしダブルクオートで囲った場合だけで、シングルクオートで囲うと評価されない

alstamber/Egofav (last edited 2012-12-10 02:31:08 by alstamber)