月曜日までに考えておきます

ITネタとゲームネタ中心に興味のあること色々書きます。

Rails3.1で作ったアプリをHerokuに公開した話のまとめ

ちょっと書くのが遅くなってしまいましたが、一ヶ月ほど前にherokuに公開した"TwitRL"の開発について語ります。 TwitRL -Twitterで最近フォローした人のリストを作るサービス- このサービスの機能は「最近フォローした人を一覧表示し、Twitterのリストにスムーズに登録できること」です。 このために、Twitter APIで以下の機能を実現する必要がありました。
  1. 最近フォローした人を取得する
  2. Twitterのリストを作る
  3. Twitterのリストに選択した人を登録する
開発環境は、Ruby on Railsの3.1で、主要なgemとしてOmniAuthとruby gem Twitterを使っています。 ruby gem TwitterはかつてTwitterBotを作った時に使ったことがあったのですが、これを使おうと思い至るまでに結構な紆余曲折がありました。 TwitterBotを作ったときはRailsではなく普通にRubyのコードで書いていました。 そのとき、オススメのgemはruby gem Twitterであると書かれていて、それを使ってスムーズに作成出来ました。 しかし、RailsTwitterを使うときはTwitter-authというプラグインがおすすめという情報があったので、まずはそれにしたがってやってみようとし、大きくハマりました。 ---ハマったところここから--- まず、やろうとしていることがこちらのブログに書かれていることに近かったのでこれを参考に勧めてみようとしました。 1時間でツイッターサービスを作ろう! | KRAY Inc Rails使ってるしheroku使っているし、ほぼこのまんま行けそうだな、と思ってやってみたところ、プラグインは入ったのですが、 $ rails generate controller のコマンドを入れたあたりで、プラグイン依存のエラーが。 そもそもRails2の時の情報だったので、Rails3では使えませんでした。 というわけで、さらにググって出たのが以下のサイト。 Railsでtwitterサービスをつくる(続き) - ありえないなど、ありえない これでRails3でも twitter-auth使えるんだ!と思って早速入れてみたところgeneric_user tableとかいう作った覚えのないテーブルへのアクセスでエラーが出たとかで動かず。 どうも、Rails3.1以降だと動かないことがいろいろあって発覚。 Rails3.0.x系にする必要がありました。というわけで、Rails3.0.11にしてみました。これで光が見えてきたと思ったのですが・・・。 使いたい機能が使えなかった・・・。 無事にTwitter-authを入れ、自分の開発PCでツイートする=>成功!herokuにアップしてツイートする=>成功! となったので、これで無事にTwitterAPIが使えると思い、早速「1.最近フォローした人を取得する」を実装しようとしました。 が、ここでまた失敗。 自分のフォローしている人が取れない。どうやっても取れない。 でもツイートするAPIは使える。 相当ハマりつつ、Twitterの各種APIを試して見ることに。そうすると、どうも最近新しくなったAPIに対応していないっぽい。 ツイートするとか、ユーザー情報を取るとかはできるのですが、おすすめユーザー機能とか、ここ一年ぐらいでTwitterに新しくできたAPIは使えないようでした。 自分のフォローした人の取得。Twitterユーザー的に見ると、こんな機能昔からあるじゃん、という感じなのですが、実はこれもここ最近でAPI仕様が変わっています。 以前は「フォローしているユーザーの情報を返す」というAPIだったのですが、通信データ量の削減のためか、「フォローしているユーザーのIDを返す」というAPIに変わりました。 で、Twiiter-authはこちらの新しいAPIに対応できていないのでこのGemを使って実装することはできないという結論になりました。 これ↓ GET followers/ids | Twitter Developers ---ハマったところここまで--- というわけで、Twitter-authは諦めてイチから作り直すことに。 Rails3.1 Twitter連携で改めて検索し、ヒットしたのが以下のサイト。大変参考になりました。 Rails3.1でTwitter認証しTwitter APIを呼び出す - naoty_k's blog 結局、いろいろと遠回りましたが Ruby Gem Twitterは偉大だと。あとOmniauth使いました。 OmniAuthでいわゆる「Twitterアカウントでログイン」的なことが実装でき、アクセスしてきたユーザーのAccessTokenとAccessSecretが取得できます。 これが取得できればこっちのもんです。 Ruby Gem TwitterTwitter APIへのアクセスが簡単に出来ます。 Ruby Gem Twitterは頻繁にメンテされているので、使えないAPIとかないみたいですね。 ただし、バージョンアップはそのぶん激しいので、日本語の解説ページだけでは不足で最新の公式ドキュメントを読む必要があると思います。 日本語のページ Route 477 - Ruby Twitter Gem簡易リファレンス 公式ドキュメント File: README ― Documentation by YARD 0.7.5 APIにアクセスできるようになるまでに手こずりましたが、そもそもやりたいことって以下の3つだったので実装自体は簡単に出来ました。
  1. 最近フォローした人を取得する
  2. Twitterのリストを作る
  3. Twitterのリストに選択した人を登録する
1.最近フォローした人を取得する これは普通にユーザーIDベースでフォローした人を取得すると新しい順に並んでいるので、それを表示するだけでOKでした。 2.Twitterのリストを作る 3.Twitterのリストに選択した人を登録する Twitterのリストを作るAPIがあるのでそれを使えばできました。 そしてリストにユーザーを追加するAPIを使って、選択した人の登録、も実現できます。 画面でユーザーにチェックボックスでリストに入れたい人を選択させ、ControllerにIDの配列を渡します。 最初、このIDを一つ一つリストに追加する処理を書いていたのですが、これだと毎回TwitterAPIにアクセスが行くので
  • 遅い
  • API使いすぎ(今って1IDあたり1時間300ぐらいでしたっけ・・・。)
という問題がありました。 でも、すぐに配列でIDを渡して一気に登録するAPIが見つかったのでそれで解決できました。 でも、こっちも20人以上一気にやるとTwitter側からエラーが返される問題が本番に出したあとに発覚:(;゙゚'ω゚'): 10人なら落ちないことがわかったので、かなり汚いコードですが10人ずつリストに追加する方法で対応しました。 リストを作ってメンバーを10人ずつ入れるコード。 はい。マジックナンバー入っててよろしくないですね。そのうちリファクタリングします。 #リスト名 @list_name = "TwitRL_#{Date.today}"

リストに突っ込む

newList = Twitter.list_create(@list_name)

2回に分けてやる

Twitter.list_add_members(newList['id'], targetMembers[0..9]) if targetMembers.length > 10   Twitter.list_add_members(newList['id'], targetMembers[10..19]) end
コードはGitHubで管理していました。 ここです。 ryonext/TwitRL GitHubで管理していたのでHerokuに上げる時も簡単です。 注意点として、Rails3.1の場合、CSSファイル等をPrecompileしないといけないということ。 これはHerokuの問題ではなくローカルのProductionモードで動かした時点でActionViewのTempateErrorとかいうエラーになります。 その解決方法はこうでした。 bundle exec rake assets:precompile RAILS_ENV=production それと、CosumerKey,CosumerSecretはいちおうアプリごとの機密情報なのでGitHubに入れるのはあまり望ましくないです。 これを実際の値を入れずに、GitHubやHerokuに上げるには、ソースファイルには以下のように記述します。 ENV['consumer_key'] ENV['consumer_secret'] そして、ターミナル等からこうやって設定します。 heroku config:add consumer_key="consumer_keyを入力" とはいえ、ローカルで作っているときは当然このHerokuの機能が使えないので、実際の値を入れる必要があります。 そうすると、git statusがこのファイル更新されてるよーと言ってきます。 いや、この変更はコミットしたくないんだよと。でも git add . でこれ以外の変更内容は一気にコミットしたい。 つまりこいつの変更がgitに補足されるのは嫌。 というのはこのコマンドで対応出来ました。 git update-index --assume-unchanged [変更を補足されたくないファイル] .gitignoreは「このファイルをgit管理しない」という設定ですが、initialize/omniauth.rbはherokuにあげる必要があるので、管理する必要はあるのだよ、と。 やりたかったのは「一切管理しない」ではなく、「これ以上ローカルの変更をコミットしない」だったので、これは知れてよかったです。 あと、エディタはVim使いました。MacVim。まだぜんぜん使いこなせてないですが。 Rails.vimとProject.vimあたり便利ですね。最近はProject.vimからNERDTreeに乗り換えました。 と、紆余曲折ありましたが無事にHerokuにRails3.1で作ったアプリを公開、ということができてよかったです。 最近、CSSJavascriptを覚えたので、そのへんの技術も適用してもうちょい見た目をリッチにしてみようかな、と計画中です。