Archive
Rails + Physical Computingする時の注意点
最近まわりでRailsが流行っているんだけど、なんだか2ケタ以上の人が「webサービスと何か(?)をするにはRuby on Railsを使えば全部できる」という盛大な勘違いを起こしているので説明用資料を書いておく。Railsはそんなに万能ではないです。
Railsはwebアプリケーションを簡単に作れるMVCフレームワークで、HTTPを通してwebブラウザから使う事を前提にしている。マイコンとProcessingを接続してガジェットを作るのとは別の常識があります。
■Railsが向いていること
Railsは、おおざっぱに列挙するとこんなアプリケーションに向いています(無理すれば変な事も可能だけど後述)
- アクセスしたURLに応じて異なるHTMLやXMLが表示される
- 後ろにSQLなどのデータベースがあって、データを溜めたり取り出したりする
- ユーザ登録してログイン/ログアウトできて、同じURLでもユーザ毎に違うHTML表示が出る
- Formがあって、テキストを打ち込んで「投稿」すると保存される
普通のwebサービスを作るのに向いています。例えば
- mixiとかFacebookのようなSNS
- WordpressやMovableTypeのように記事をFormに打ち込んでデータベースに保存して、週毎/記事毎の様々な表示で同じデータを使い回す
- twitterや掲示板みたいなもの
ようするに、あるURLにHTTP GETでアクセスすると何か表示される。そしてHTTP POSTするとデータを溜めるという機能がある。
Read more…
GoogleEarth上でFlickrの位置情報付き写真を見れるサービスを作った
blogを書けなくて(MTが再構築できなくて)もう1ヶ月ぐらい前に作ったものになるけど、春休みにRuby on Railsのお勉強をしていて、その最終成果物としてGoogleEarth上でFlickrのGeoTag付き写真を見れるサービスを作ったのでまとめておく。
ついでに、緯度経度でFlickrの写真を検索できるAPIも公開してある。
■実装方法
1.Flickrのタグ検索で、geotagが付いている写真を定期的にクロールしてきて、写真のURL、緯度経度をRailsのDBに溜める(photo modelに溜める)
2.GETパラメータで緯度経度をRailsに渡して、photo modelを検索する
3.検索結果をGoogleEarthで表示できるように、kml出力のViewを作る
4.GoogleEarthで視点が変わる毎にサーバーに問い合わせて、返ってきたkmlを表示するkmlを作る
5.mongrelでRailsを動かして、apache2のmod_proxy_balancerでRailsのURLをサブディレクトリに見せかける
こんな感じで。一番時間がかかったのが1のクローラの実装で、これは俺がRuby初心者すぎて2日ぐらいかかった。あとは、デンマーク行きの飛行機と帰りの空港からのバスでやったので5時間ぐらい。この辺は、データを溜めて、クライアントからのリクエストに基づいてフォーマットを決めて吐き出す部分が最初からできてるRailsのおかげ。
■1.geotag付き写真クローラ
まずFlickrはタグ検索ができるけど、数値じゃなくて「〜〜を含む文字列」としてしか検索できないので、例えば「北緯35度東経135度周辺の写真が欲しい」という時は使えない。なので、あらかじめメタデータを集めておいて、数値として範囲を指定して検索できるようにしておく。
geotagは小数点ありの値(geo:lat=35.2341など)なんだけど、普通にgeo:latやgeo:lonを含む写真一覧をFlickr APIから検索しても小数点無しのタグしか手に入らない。
小数点ありのタグを手に入れるために、Net::FlickrでFlickrAPIからタグ検索して、
→ Net::Flickrで全public photoからタグ検索 – shokaiの日記
“geotagged”タグを含む写真をリストアップして、それから再度photo_idを使ってFlickrAPIのphotos.getInfoメソッドを使ってtagのraw attributeを見なければならなかった。
→ s.h.log » RubyでFlickr APIのphotos.getInfoを呼ぶ
クローラ自体はRailsで実装されていなくて、ActiveRecordだけを使ってcronで1時間毎に実行されている。
→ s.h.log » RailsなしでActiveRecordだけ使って、SQLiteを読み書きする
SQLiteのファイルがRailsと共有されているだけ。今回は、Rails側からの書き込みが無いので特に問題は起こらないだろうと判断した。
いまのところ10万枚の写真が集まった。SQLiteのファイルが欲しい人はあげます。
あと、クローラは連続でHTTPアクセスするとFlickrに悪い気がするので、適当にsleepを入れてみてるんだけど、そうすると実行に結構時間がかかる。これが、クローラを作って動かして直して作って…と繰り返す時に面倒だったが、和田さんに言われてscreenをデタッチ/アタッチするという技を覚えた。デタッチしておくと、sshを切断してもクローラが止まらなくて、アタッチしたら普通に続きからできる(もしくは結果が出てる)screenはクローラ作ってるときに重要。
■2.緯度経度をGETパラメータでRailsに渡して検索する
photos.kml?lat=35&lon=135&size=thumb
みたいな形式で、パラメータを渡してDBに溜めた写真を検索する。
→ KMLを全部出すと多すぎたので、緯度経度を指定してその周囲の写真だけ出す – shokaiの日記
paramsで受け取れる。パラメータ名はシンボルになっているので注意。
controllerで、ActiveRecord::Baseのfind_by_sqlメソッドで普通に検索。(この方法だと四角い。PostgreSQLやMySQLの空間型を使えば丸くできるらしいがとりあえずSQLiteでやる)
そしてmodelの配列をViewに渡してやる。
■3.検索結果をGoogleEarthで表示できるように、kml出力のViewを作る
kml形式のviewを作る。views/photos/index.html.erb を参考にして、index.kml.erbを作ればok
mime-typeにkmlを追加しておく必要があった。
→ flickrのgeotagついてる写真を収集してたので、kml出力するようにした – shokaiの日記
結果は巨大なkmlになるので、Rails標準搭載のWEBrickだときつい。でかいときはhttpサーバーをmongrelに換える。
→ MongrelでRailsをデプロイ – shokaiの日記
→ apache2のサブディレクトリをmongrelで起動してるrailsにプロキシする – shokaiの日記
■4.GoogleEarthで移動する毎に検索するkmlを作る
GoogleEarthの表示を作っているkmlは、静的な表示だけでなく、NetworkLinkタグで別のKMLの内容をURLを指定して読み込める。さらにViewRefleshModeをonStopにすると、画面の移動が止まった時に再読み込みできる。
再読込時に、視点の緯度経度を[lookatLat][lookatLon]で取得できるので、
lat=[lookatLat]&lon=[lookatLon]
としてNetworkLinkで読み込むkmlのURLの後ろにくっつけてやる事で、GETパラメータになる。
→ GoogleEarthで表示している場所の緯度経度から検索する – shokaiの日記
■5.mongrelでRailsを動かして、apache2のサブディレクトリに見えるようにする
デプロイ。
4まではMac OSX上でやって、ここからは大学院棟に置いたUbuntuに移し替えた。RailsをSQLite+Mongrel環境で動かして、URLをapacheで隠すようにすると、Railsプロジェクトのディレクトリをそのまま移し替えるだけでほぼ動くので超楽。
→ Flickrのgeotag写真を検索する – shokaiの日記
→ apache2のサブディレクトリをmongrelで起動してるrailsにプロキシする – shokaiの日記
→ MongrelでRailsをデプロイ – shokaiの日記
→ Mongrel入れる – shokaiの日記
———–
こんな感じで、クローラの実装と、バックエンドのサービスとしてAPIを吐くためのRails、というのを覚えた。
今まで戦略的に「長い時間をかけたインタラクション」をするモノや、「データを共有した複数のモノと人とのインタラクション」を作る事を避けていたんだけど(ややこしくてプロトタイピングできないものは作らない方針なので)
Rails使うとサクサクとこのぐらいまではいけるようになったので、自分の得意なフィジカルなデバイス作成と合体させて何か新しい物を作る予定。
RailsにFlashからpostしたり取り出したりする
Railsのscaffoldでさくっと作ったインタフェースって、HTTP-POSTからSQLに保存したり取り出したりもできて色々プロトタイプを作るのに便利なのでまとめておく。
ためたデータの管理もできるし。
■Rails側の準備
まずrailsを入れる。
Macの人は既に入っているはず。Windowsなら、ActiveScriptRubyを入れてパス通すと、gemコマンドが入るのでgem install railsすればrailsコマンドが使えるようになる。DBはSQLiteのdll版をc:\windows\system32に入れればできる様になるはず。
railsでtestbbsというプロジェクトを作って、そこにscaffoldでentry(投稿)というmodelを作る。entryには、name(投稿者)とmessage(本文)が入る。
rails testbbs
cd testbbs
ruby script/generate scaffold entry name:string message:text
rake db:migrate
(単数形に注意)
webサーバーを立ち上げる
ruby script/server
http://localhost:3000/entriesから見れるようになっている。はず。(複数形に注意)
こんなページができている。ここからentryを増やしたり消したりもできる。

ここまでで、http://localhost:3000/entries/newから投稿できるのと、http://localhost:3000/entries.xmlから一覧を取得できるようになった。
→Source Code (Ruby on Rails 2.0.2)
■Flashから投稿する
HTTP POSTで行う。
今回作ったもの(動きます)
Source Code (AS3 / Flash CS3 + Flashdevelop)
今回もFlashDevelop上でAS3書いて、FlashCS3オーサリング/コンパイルした。
こいつでPOSTすると、http://localhost:3000/entriesに結果が出るようになる。

どうやってるかというとまず
http://localhost:3000/entries/newを見ると
Message
という風にPOSTしているので、entry[name]とentry[message]をパラメータで渡せばいいとわかる。


最近のコメント