さて、前回の下準備を経てようやく本題です。
先日のJTPAのギークサロンで、飛ぶ鳥を落とす勢いのRockYouの創業メンバーである石塚さんがFacebookアプリの作り方をハンズオンで教えてくれたのがすごく面白かったので、ちょっと自分でも遊んでみました。試しにRailsで作ってみたので、その手順を紹介したいと思ったのが今回の動機。
Facebookではサクッと作って出したアプリが3日で100万ユーザとかいうことが普通に起きているらしく、石塚さんいわく「そういうヒット作を作ったら、RockYouがン千万円で買い取るよ」だそうです。気合い入りますね。:)
環境:
開発機:Mac OS X (Leopard or Tiger)
サーバ:Linux (Debian Etch)
フレームワーク:Ruby on Rails (2.0.2)
目標:Railsを使って自分の友達リストを取得・一覧するFacebookアプリを作ってみる
動作イメージ:
Facebookアプリケーションの典型的な動作イメージは、だいたい以下のような感じです。
このダイアグラムを頭に入れて次へ進みます。
サインアップは当然必要なので、とっとと済ませましょう。
友達がいないと激しくつまらないので、同時に誰かを誘うと吉です。あるいはKenn Ejimaで検索してぼくをAdd To Friendsしてくれて構わないのですが、もれなく飼育中の吸血鬼に噛みつかれたりゾンビに喰われたりすると思いますので、その点はご了承ください。
Facebook DevelopersのページからGet Started → Add Facebook Developer Application をクリックして「Developer」というアプリケーションを追加。
これで左側のアプリケーション一覧の「More...」のところに「Developer」が表示されていればOKです。
その「Developer」をクリックして、右上の「Set Up New Application」をクリックします。
ここでOptional Fieldsを展開し、実際に設定していきます。具体的に設定が必要なのは以下の3つです。
Application Name:
あなたのアプリケーション名です。今回は「My First Facebook Demo」とします。
Callback Url:
あなたのRailsサーバが稼働するURLです。生IPやDynamic DNSでもOKだと思います。今回は「http://bar.com:3000/」とします。
Canvas Page URL:
Facebook内からそのアプリケーションにアクセスするためのURLです。今回は「foo-demo」とします。
あとは規約に合意のチェックボックスをチェックして保存すると、以下のように登録が完了します。
ここで発行されたAPI KeyとSecretは後で必要になるのでメモしておきます。
これでFacebook側の準備は完了です。
前回、Railsのセットアップまでは完了しているので、Rails用のFacebook APIライブラリであるRFacebookをインストールしましょう。
ここに書いてある通りにやればいいのですが、前回からの流れに沿ってゼロからという前提で説明すると、まずSubversionをインストールしておきましょう。
$ sudo port install subversion
次に、RFacebookのインストール。
$ sudo gem install rfacebook
最後に、RFacebookのRails Plug-inのインストール。
$ cd ~/Documents/rails-demo $ script/plugin install svn://rubyforge.org/var/svn/rfacebook/plugins/rfacebook_on_rails A /Users/[Your_home]/Documents/rails-demo/vendor/plugins/rfacebook_on_rails A /Users/[Your_home]/Documents/rails-demo/vendor/plugins/rfacebook_on_rails/test A /Users/[Your_home]/Documents/rails-demo/vendor/plugins/rfacebook_on_rails/test/test_helper.rb (中略) A /Users/[Your_home]/Documents/rails-demo/vendor/plugins/rfacebook_on_rails/install.rb A /Users/[Your_home]/Documents/rails-demo/vendor/plugins/rfacebook_on_rails/uninstall.rb Exported revision 54.
ここまででインストールは完了です。
続けて、RFacebookとfacebook.ymlの設定です。同じく rails-demo ディレクトリで以下を実行します。
$ rake facebook:setup (in /Users/[Your_home]/Documents/rails-demo) ====================================================== Setting up RFacebook on Rails Plugin [1] Created config/facebook.yml <-- BE SURE TO CHANGE THE API KEY AND SECRET Done. ======================================================
この手順でconfigディレクトリにfacebook.ymlというファイルが生成されたので、これを編集します。今回は開発マシン上で作業をするので、development環境を設定します。
development: key: YOUR_API_KEY_HERE secret: YOUR_API_SECRET_HERE canvas_path: /yourAppName/ callback_path: /path/to/your/callback/ tunnel: username: yourLoginName host: www.yourexternaldomain.com port: 1234 local_port: 5678
これを、先ほどFacebookに登録した情報に従って変更していきます。
development: key: 2024a5994d0f655912bc0c6f0acdffff ... 登録時に発行されたAPI Key secret: 566eb41e9c33f9100af3eb50e9deffff ... 登録時に発行されたSecret canvas_path: /foo-demo/ ... 登録した Canvas Page URL callback_path: / ... Canvas Page URLと1対1で対応するローカルのルートパス tunnel: username: foo ... サーバのアカウント host: bar.com ... サーバのホスト名またはIPアドレス port: 3000 ... サーバのポート番号 local_port: 3000 ... 開発マシンのポート番号
最後の「tunnel」パラメータ群は、とりあえず無視しておいても構いません。
ちょうどこのブログを書いている時にRailsのバージョンが2.0.2へと変更になり、デフォルトのデータベースがMySQLからSQLite3へと変更されました。
この変更のおかげで、データベースを含めた初期セットアップが圧倒的に簡単になっています。というのも、SQLite3本体はMacに標準添付だからです。
今回はDBを使わないのですが、せっかくなのでこの機会にSQLite3をセットアップしてDBが使える通常の状態にしておきたいと思います。
まず、前回の手順6で config/environment.rb にDBを使わない設定をしてあった場合、その行を取り除きます。
また、Rails 2.0.2よりも古いものを使っていた場合には、以下を実行してRails本体をアップデートし、SQLite3のRuby用クライアントライブラリ(Leopardはこれも標準添付)をインストールしておきましょう。
$ sudo gem install sqlite3-ruby # Leopardの場合は不要 $ sudo gem update rails $ rails -v Rails 2.0.2
そして config/database.yml が以下のようになっていることを確認してください。
development: adapter: sqlite3 database: db/development.sqlite3 timeout: 5000
なっていなければ、作成した rails-demo ディレクトリをゴミ箱に捨て、復習を兼ねてRails 2.0.2ベースで前回の手順を手順4からやり直すのが手っ取り早いでしょう。
次に、Railsディレクトリで以下を実行してデータベースを初期化します。
$ rake db:migrate
さて、この手順で生成されるデータベースの実体は db/development.sqlite3 というファイルになります。この設定は config/database.yml に書かれているものが使われます。
次に、SQLite3にアクセスしてみましょう。
$ sqlite3 db/development.sqlite3 SQLite version 3.3.13 Enter ".help" for instructions sqlite> .schema CREATE TABLE schema_info (version integer); sqlite> .quit
こんな感じで対話的にデータベースを操作できます。
以上でデータベースのセットアップは完了です。
さて、今回の最大の山場です。
Facebookのアーキテクチャは、サーバがグローバルIPを持っていることを前提としています。
ここで取れる選択肢は二つです。
前者は、ルータのグローバル側IPアドレスをFacebookに登録し、ルータのポートフォワード設定で3000番を開発マシンにつなぐか、思い切って開発マシンをDMZに置いてしまうなどします。いずれも一般的な家庭用のルータで設定が可能だと思います。
後者は、外部に置いてあるサーバにSSHでトンネルを空け、その外部サーバの3000番にアクセスがあったときに、それを開発マシンの3000番へと転送させるというアクロバティックな方法です(そのサーバのルート権限が必要です)。
ここでは後者の方法について説明します。
まず、サーバにログインし、SSHサーバの設定を変更します。
おそらくデフォルトではSSHトンネルは外部からのアクセスを許可していません。そこでDebianの場合、
$ sudo vi /etc/ssh/sshd_config
を実行し、
GatewayPorts yes
という行を追加(あるいはGatewayPortsの設定がすでにある場合には変更)します。そして設定を反映するため、SSHサーバを再起動します。
$ sudo /etc/init.d/ssh restart
これで、Facebookからサーバへのアクセスを開発マシンに転送できるようになりました。 config/facebook.yml の設定を確認してから、新しくターミナルウィンドウを開いて以下を実行します。
$ cd ~/Documents/rails-demo $ rake facebook:tunnel:start (in /Users/[User_home]/Documents/rails-demo) ====================================================== Tunneling bar.com:3000 to 0.0.0.0:3000 (中略) ====================================================== Password:
ここで入力するパスワードは、サーバのパスワードです。この状態で待ち状態になっていればひとまずOKです。
次に、開発マシン上のrailsを起動してみましょう。上記のSSHトンネルを実行しているのとは別のもう一方のターミナル上で
$ cd ~/Documents/rails-demo $ script/server
を実行します。
ここまできたら、ブラウザで
http://bar.com:3000/
にアクセスして、RailsのWelcomeページが表示されれば成功です。
ここで注目すべきは、bar.com上では3000番を待ち受けしているプロセスは存在しておらず、あくまでSSHトンネルによって開発マシン上で動いているRailsがこの画面表示を実行しているということです。ちょっと不思議な感じがしますが、デバッグにはとても便利です。
さて、いよいよ準備が整いました。
前回作成した app/controllers/hello_controller.rb をテキストエディタで開いてみましょう。
class HelloController < ApplicationController def world render(:text => 'Hello World!') end end
これに2行加えて以下のように変更します。
class HelloController < ApplicationController before_filter :require_facebook_login skip_before_filter :verify_authenticity_token def world render(:text => 'Hello World!') end end
この skip_before_filter の行は Rails 2 で導入されたCSRF対策が RFacebook と相性が悪いので、チュートリアルの都合上いったん無効にしてしまうおまじないです。詳しくはこちら。
さて、いよいよ実行してみましょう。
手順6で、2つのターミナルでRailsとSSHトンネルのそれぞれが実行中であることを確認します。
$ rake facebook:tunnel:start
$ script/server
さて、ブラウザから
http://apps.facebook.com/foo-demo/hello/world
へとアクセスしてみましょう。ここで /foo-demo/ 以下が開発マシンの / 以下とマッピングされ、Facebookからは http://localhost:3000/hello/world がアクセスされていることに留意してください。
上のように「Hello World!」がFacebookのページに埋め込まれて表示されていたら成功です!
いよいよ大詰めを迎えました。
先ほどHello Worldを表示した箇所には通常のHTMLタグや、FBMLと呼ばれるFacebook独自のタグを埋め込むことが可能です。
また、SQLライクなFQLという問い合わせ言語により、同じセッション内で、今度は逆方向にサーバからFacebookに問い合わせてデータを取得することが可能です。
今回は RFacebook というライブラリを使っているので、FQLを直接さわることはありませんが、内部的にはそういうものを呼んでいるのだと知っておくとよいでしょう。
さて app/controllers/hello_controller.rb に友達一覧を表示する friends というアクションを追加してみましょう。
class HelloController < ApplicationController before_filter :require_facebook_login skip_before_filter :verify_authenticity_token def world render(:text => 'Hello World!') end def friends friendUIDs = fbsession.friends_get.uid_list @friendsInfo = fbsession.users_getInfo(:uids => friendUIDs, :fields => ["first_name", "last_name", "pic_small"]) end end
fbsession は require_facebook_login によってセットされるセッションオブジェクトで、friends_getは facebook.friends.get を呼んでいます。その結果得られたUser IDのリストをローカル変数friendUIDsに格納し、次にそのUser IDのリストをもとに users_getInfo で facebook.users.getInfo を呼んでいます(そろそろ命名規則がわかってきたかな?)。こんな感じで、fbsessionを使ってあらゆるFacebook APIメソッドにアクセスできます。
そして、実際に取り出したいフィールドをFQLデータ定義一覧から取り出し、Viewからも参照できるように@friendsInfoというインスタンス変数にセットしています。
今回はrenderメソッドではなく普通にViewから表示したいので app/views/hello/friends.rhtml というファイルを作成し、以下のように書き込みます(Rubyの書き方やテンプレート書式eRubyについては説明を省きます)。
<h1>Hello Friends!</h1> <ul> <% @friendsInfo.user_list.each do |friend| -%> <li><%= image_tag(friend.pic_small) %> <%= friend.first_name %> <%= friend.last_name %></li> <% end -%> </ul>
これで完成です。ブラウザから
http://apps.facebook.com/foo-demo/hello/friends
を実行してみてください。これで以下のように表示されたら成功です。
うまくいきましたか?
ぼくの環境はもうだいぶ手垢がついてて、本当に初めてやる人がうまくいくかどうか知りたいので、うまくいったとか、うまくいかなかったとか、フィードバックいただければ、しばらくエントリをアップデートしておくようにします。
ともあれ、これでもう皆さんはRailsを使ってFacebookアプリが開発できるようになりました。ぜひ誰かRockYouに売れるようなサービスを作って一山当ててください。:)
♪ Genesis / Follow You Follow Me
※このエントリは CNET Japan ブロガーにより投稿されたものです。シーネットネットワークスジャパン および CNET Japan 編集部の見解・意向を示すものではありません。
yoichiro on 2007/12/20
そういうディティールは重い腰が上がって作り始めたら自分で対処すればよいことではないでしょうか?そもそもfacebook API自体が日々コロコロ変わっているわけだし、rfacebookではFQLを直接扱えないのでたぶん本番では使えないだろうなぁとか不満は色々あります。でもライブラリの追い出しなんて理解度・本気度が上がってきてからじっくりやればよいのです。まずはhello worldが動いたという喜びを燃料に入り口の敷居を下げてナンボだというのがぼくの考えです。もちろん違った考え方もあるでしょうけど、じゃぁこのエントリ自体書かないでぼくの頭の中の知識にとどめておいた方がマシだったほどまずい内容でしたでしょうかね。
kenn on 2007/12/20
rfacebookを使ってアプリを開発しています。上記のような「単にHello World!が表示されたので、あとは開発ばっちりです!」的な内容は、現状のrfacebookの品質を考えると、とても危険ではないでしょうか?せめて、rfacebookを使って「基本的なアプリ(Ajax含む)」を作ってみてから投稿すべきだと思います。実際、rfacebookのforumにあるパッチコードを当てないと、使い物になりません。そういった点で、上記内容は残念です。
yoichiro on 2007/12/20
ブログにコメントするにはCNET_IDにログインしてください。
この記事に対するTrackBackのURL:
メンバー限定サービスをご利用いただく場合、このページの上部からログイン、またはCNET_ID登録(無料)をしてください。
http://jypsie.com/RFacebook/forums/RFacebook-Help/topics/more-facebook-sessions-problem-