223 Software

主に勉強したことなどを記録するログです。 最近はRuby, Railsなどが多め。

ruby - 223 Software

Rubyを始めたい方向けまとめ(2011年秋版)

最近gitやrubyなど、プログラミング関連のあれこれを教える機会が増えてきました。

今自分が一番使っているプログラミング言語はRubyですが、これをどうやって効率的に学習すればいいのかなぁということを考えてみました。

情報の入手の仕方なども盛り込んで、今後自力で使いこなしていくために必要そうなノウハウをなるべく盛り込んでみました。
これからrubyを学ぼうという方の参考になれば幸いです。

また「これからプログラミングを覚えて何かWebアプリを作ってみたいけれど、とっかかりが見つからない。」という方にとっても何かしらきっかけを与えることができたなら幸いです。

ご注意

  • 僕自身はWeb系のプログラマのため、そちらの分野に偏った内容となっています。
  • この分野の情報はすぐに古くなります。1ヶ月後にはトレンドが全く変わってしまっている可能性がありますので、新しい情報を常に参照するように気をつけてください。(自戒をこめて)

目次

開発環境の構築

まずは開発できる環境を整えたいと思います。

ここでは執筆時点で最もモダンだと僕の考える方法で環境構築をしてみます。

マシンの準備

Windowsでも動きますが、Macユーザーが極端に多いです。特に初級者の場合は教えてくれる人がなるべく多い環境を選ぶ方がいいのでMacをおすすめします。

勉強会で大人気のMacBook Airですが、だいぶ安く買えるようになりました。
ruby系の勉強会に行くと、参加者の9割はMacで、そのうち半数以上がAirということもざらです。

ここから先はMac OS X 10.7 (Lion)の環境を対象にして進めてしまいます。

Xcode

rubyのコンパイルや、一部のライブラリのインストール時に必要になります。
また、データベースなどの開発に必要なミドルウェアのインストールにも使われます。
デフォルトでは入っていませんので、App StoreからXcodeをインストールしてください。(無料です。)

App Storeへのリンク

Homebrew

Homebrew

パッケージ管理システムと呼ばれるソフトウェアの一つで、開発に必要なソフトウェアの管理に使います。

従来はMacPortsが主流だったのですが、今はかなり多くの開発者がHomebrewに移行しています。

ターミナルで以下のように打ち込むことでインストールできます。

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"
バージョン管理

rubyの場合、実質gitがデファクトスタンダードです。GitHub上で開発されているライブラリもたくさんありますし。

Lionの場合、Xcodeをインストールすれば一緒に入るはずです。

コマンドラインでの操作が苦手な方も、GUIのGitクライアントも増えてきましたので安心です。

あとはgit guiとすると、GUIのクライアントが立ち上がると思います。

rubyのインストール

現在最新の安定版のrubyはバージョン1.9.2ですが、まだまだ1.8.7も多い状況です。OS Xに始めから入っているrubyも1.8.7です。
これから何か新しいプログラムを書くのであれば、1.9.2で問題ないと思います。

追記: 先ほど1.9.3がリリースされたらしいので、そっちが最新ですね。ちゃんと確認していないので取り急ぎ。

ちなみにrubyのインタプリタ(ソースコードを解釈して実行してくれるプログラム)にはいくつかの種類があります。

特に理由が無ければMRIを入れておけば間違いないです。

rubyに限らず最近のスクリプト系言語(LL: Lightweight Languageと呼ばれたりする。perlとか、pythonとか、node.jsとか)の開発者の多くは複数のバージョンを切り替えて扱えるようなツールを使っています。

rubyで言うと、以下の2つが主流です。

最近人気が高まってきているのはrbenvの方ですが、まだまだユーザーはrvmの方が多いと思います。
身近に教えてくれる人がいるのなら、その方に合わせてください。
いないようなら、とりあえずはユーザーの多いrvmがいいと思います。

RVM: Ruby Version Manager - Installing RVM のページの"Single-User installations"の手順に従って作業をすれば、それだけでruby 1.9.2を使うモダンな環境が出来上がります。

またrbenv + ruby-buildは僕の個人的なおすすめです。こちらにチャレンジする方は以下のエントリーを参考にしてください。

rbenv + ruby-buildのインストール方法

エディタ

以下のものが人気が高いみたいです。自分に合ったエディタを探してください。

サーバー

Webアプリケーションを作ったとして、それを動作させるサーバーがないと一般公開できません。
幸い、今は無料でアプリケーションを素早く公開することもできるようになりました。

今ruby開発者の間でもっとも広く愛用されているのはherokuです。
gitでpushするだけでアプリケーションを公開でき、無料でもかなり使えますのでまずはこれを使う方向でいいと思います。

サーバー構築ができる方はVPSやIaaSも検討されるといいと思います。
apache or nginx + passengerがお手軽です。

ちなみにこのブログはさくらのVPS にインストールしたapache + passengerで動いています。

おすすめの学習方法

手っ取り早く体系立てて学ぶには本を読むのがいいと思います。rubyの書籍はたくさんありますが、中でもおすすめの2冊を紹介します。

他の言語を学んだことがある方は、「初めてのRuby」がおすすめです。薄い本なのですが、rubyらしい考え方のエッセンスが詰まっています。

rubyの文法や文字列操作、配列、メソッド定義などの基本的な内容に加え、ブロックやメタプログラミングの入り口まで含まれています。

基礎を固めたあとは「メタプログラミングRuby」がおすすめです。

例えばActiveRecordなど、rubyのよく使われるライブラリはメタプログラミング(通称:黒魔術)を駆使して書かれていることが多く、メタプログラミングの知識無しでは使いこなすことが困難です。

あとはせっかくherokuもあるしアプリケーションを書いてみるのがいいのですが、いきなりrailsにいくと覚えることの多さに挫折してしまうかもしれません。
個人的にはまずsinatraで作った簡単なマッシュアップ程度のアプリケーションを公開してみるのが手軽かつ面白いと思います。
例えば以下のようなアプリケーションを作ってみるのはいかがでしょうか?

  • ATNDのイベントを検索するサイト - APIはここ
  • 楽天やYahooショッピング, amazonを横断して商品検索ができるサイト
  • 自分のツイートからURL付きのツイートを抜き出すサイト
  • Instagramに投稿された写真をタグや位置情報をもとに検索するサイト

初級レベルではsinatraだとDBに接続するまでがちょっと難しいので、DBを使う段階になったらrailsやpadrinoに行くといいかもしれません。

DBを使うプログラムの場合、ブログや一行チャット、Todoを作ってみるのが定番だと思います。
ただ、ログインの機能をつけようと思うととたんに難しくなりますので、とりあえずbasic認証とか、認証無しで。

実際、一番いいのは教えてくれる人を早めに見つけることです。
身近でruby勉強会などが開催されていないか、ぜひ探してみてください。
あとはtwitterやfacebookなどで教えてくれる人を探すのもいいかもしれません。

知っておくべきライブラリやフレームワークの軽い紹介

アプリケーションを作ろうとしたとき、必ずしも全機能を自分で実装する必要はありません。すでに色んな種類の定番ライブラリがありますので、その辺をうまく活かしていくのも素早くアプリケーションを作るコツです。

基本編

RubyGems

ライブラリの管理ツールです。1.9以降はruby本体に付属しているので特にインストールせずに使えます。

$ gem search [検索文字列] -r # ライブラリの検索
$ gem install [ライブラリ名]
$ gem update # ライブラリのアップデート
$ gem uninstall [ライブラリ名]

Bundler

これもライブラリの管理ツールですが、アプリケーション固有で必要になるライブラリの管理に使います。
railsをやるときや、herokuにアップロードするアプリケーションを作るときに触れることになります。

簡単に説明すると、Gemfileというファイルにそのアプリケーションを動かすのに必要なライブラリを列挙します。
そしてbundle installコマンドでそれらのライブラリがインストールされます。
そのライブラリはカレントディレクトリ以下の任意のディレクトリにインストールすることができるので、システムにごちゃごちゃとライブラリがインストールされること無く、アプリケーションごとにきれいに管理できるという利点もあります。


rack

直接rackを意識することはあまりないかもしれませんが、sinatraやrailsといったWebアプリケーションフレームワークはこれを利用して作られています。
rackのおかげで、thinやpassenger, unicornなどのどのサーバーを利用してもちゃんとアプリケーションを動かせるわけです。

Webアプリケーションフレームワーク編

Ruby on Rails

言わずと知れた超有名ruby製フレームワーク。これを使いたいがためにrubyを勉強しようという方も多いのではないでしょうか。
簡単なブログ程度ならあっという間に作れるのですが、ちょっと踏み込むと高機能であるが故に覚えることもたくさんあります。

書籍もたくさんありますが、バージョンに気をつけて選んでください。今の段階だとおすすめは以下です。

あと、公式のGuidesは必読です。


Sinatra

非常にシンプルなフレームワークです。

railsで挫折してしまった人もこちらなら十分理解できるくらい覚えることが少なく、とっつきやすいです。

個人的には、これからプログラムを勉強してみたいという人にはこれを一番に推します。Webアプリの仕組みを勉強するのにもとても向いていると思います。
ちなみに次点はレンタルサーバーを借りることを前提としてPHPでしょうか。


Padrino

最近これをテーマとした勉強会も開かれ、勢いがあります。

railsでは大きすぎるし、sinatraではちょっと足りない、そんなニーズに応えるものです。管理画面が作りやすいのも特長ですね。

データベースアクセス編

ActiveRecord

railsの一部のように思われがちですが、単独で使うこともできます。なのでsinatraで利用することなどもできます。


DataMapper

特長はMongoDBやredisなどのNoSQLのアダプタもあることでしょうか。
ruby製の人気CMSであるLokkaでもこのライブラリを使っています。


Sequel

ActiveRecordやDataMapperよりももうちょっと生のSQLに近いAPIのライブラリという印象です。
SQLがわかっていると、とてもわかりやすいAPIだと思います。

cheat sheet


Mongoid

MongoDBを使う際、今一番使われているライブラリだと思います。

ほぼActiveRecordと同じようなAPIが準備されているので、すんなり使い始めることができます。
それでいて、ちゃんとEmbedded DocumentなどのMongoDBの特長も活かせるような作りになっています。


Redis

高機能NoSQLのRedisのアダプタです。

テンプレートエンジン編

ERB

railsのデフォルトのテンプレートエンジンがこれです。
PHPみたいに、HTMLの中にrubyのコードを混ぜて書くことができます。

<div id="profile">
  <div class="left column">
    <div id="date"><%= print_date %></div>
    <div id="address"><%= current_user.address %></div>
  </div>
  <div class="right column">
    <div id="email"><%= current_user.email %></div>
    <div id="bio"><%= current_user.bio %></div>
  </div>
</div>

Haml

慣れると簡潔にHTMLが書けるようになります。階層関係をインデントで表すので、あとからのメンテナンスもしやすいです。

好き嫌いはあると思いますが、僕はこれを使い始めたらhtmlを書くのがめんどくさくなりました。

上のERBのサンプルコードは実はhttp://haml-lang.com/から持ってきたもので、hamlで書くと以下のようになります。

#profile
  .left.column
    #date= print_date
    #address= current_user.address
  .right.column
    #email= current_user.email
    #bio= current_user.bio

Slim

Hamlから記号などを除いたらslimになるイメージです。
Node.jsでよく使われるjadeと似ているので、そっちもやっている人にはおすすめかも。

ちなみに、hamlっぽく#とか.とかを使って書くこともできます。

div id="profile"
  div class="left column"
    div id="date"= print_date
    div id="address"= current_user.address
  div class="right column"
    div id="email"= current_user.email
    div id="bio"= current_user.bio

Sass

CSSをよりスマートに書くための文法です。

Sassでは、hamlみたいにインデントで階層構造を表現するsassという書き方と、従来のCSSとほぼ同じように書けるscssという書き方の2種類があり、rails 3.1から標準でサポートされたのはscssの方です。

セレクタの入れ子ができたり、mix-inという関数みたいな仕組みや、変数をCSS中で使うことができるのが特長です。

同種のものにlessというものもあります。

テストフレームワーク編

rubyはソフトウェアテストの文化がとても深く根付いている言語だと思います。

勉強会などに参加しても必ずテストが話題にのぼるくらいです。テストでよく使われるライブラリのうち、いくつか定番を挙げます。

RSpec

現状、rubyでテストと言ったらこれがデファクトスタンダードのようになっています。うかつに検索すると古いサイトが出てきてしまいますので、これを学ぶには以下のサイトがおすすめです。

"RSpecの写経"と言われたら、上記のサイトのことです。一通りこなすといいと思います。

あとはRSpecのAPIなどは以下を見ましょう。

個人的にはRelishを一番頻繁に見ていて、モックを使おうとしたときにMocksを参照することがたまにある感じです。

追記: 上記、rubydoc.infoへのリンクが2.4.0という古いバージョンへのリンクになっていました。修正しました。


test-unit

他言語のxUnit(PHPUnitとか、JUnitとか)にあたるのがこれです。

ruby 1.8の頃は標準添付でしたが、今は代わりにminitestというのが標準添付となっています。

標準添付ではなくなってからも活発に更新されているようです。


shoulda

shoulda-matcherとshoulda-contextの2つのgemに分かれているのですが、Test::Unitでもcontextを使ってRSpecみたいにテストケースを整理することができたり、rails開発に便利なマッチャー(検証用のメソッド)が提供されていたりします。

僕は使っていないので詳しくわからないのですが、根強いファンがいるようです。


Capybara

ブラウザでの動作をエミュレートしてくれるライブラリです。テストフレームワーク?って感じですが一応ご紹介。

visit '/top'
fill_in_with 'email', :with => 'user@example.com'
fill_in_with 'password', :with => 'password'
click_button 'Login'

こんな感じに書けます。seleniumを使うことにより、実際にFirefoxが立ち上がって動いたりして、なかなか面白いです。


他にもmockのライブラリとかテストデータの作成に便利なライブラリとか色々ありますが、そこまで進む頃にはすでに初心者じゃないと思いますので割愛します。

情報の入手方法

オブジェクト指向スクリプト言語 Ruby リファレンスマニュアル

まずは公式のドキュメントです。

文法などの確認はこちらで。あと、標準添付ライブラリも便利なものがたくさんあるのでどんなものがあるのか、一通り見ておくといいです。


最速Rubyリファレンスマニュアル検索! | るりまサーチ

マニュアルの検索はこちら。


Rubyist Magazine

通称るびま。

Webで発行されているRubyist向け雑誌です。
技術的な情報のみならず、インタビューやエッセイが掲載されていたりもします。


The Ruby Toolbox

人気のあるライブラリを探すことができます。

最近リニューアルされて、カテゴリ検索に加えてキーワード検索もついて使いやすくなりました。

追記: Toolboxを間違ってToolkitって書いてました。ご指摘ありがとうございました。


RubyDoc.info

ライブラリのAPIドキュメントが見られるサイトです。個人的にとても重宝しています。


Ruby5

英語ですが、ruby関連の情報を流しているPodcastです。
英語の勉強を兼ねて通勤中によく聴いています。


RailsCasts

これも英語ですが、railsのスクリーンキャストです。
これもiPhoneに入れて通勤中に見たりしています。


あとは勉強会やコミュニティに参加するようになると、新しい情報や実務に基づいた詳しい情報なども入手することができるようになります。
あとはブログなどで自分からも情報を発信するようにすることで、色んな人とのコミュニケーションができるようになり、結果色んな情報が集まるようになったりもします。

あんまり優良な情報を発信しようと無理に意気込むのではなく、とりあえず自分が試してみたことやうまくいかなかったことなどを気軽にメモるようにしておくと、結構教えてもらえたりします。

コミュニティ/勉強会

ということで、コミュニティや勉強会です。

まずは 地域Rubyの会 を探してみるといいと思います。
まぁ、やっぱり首都圏が多いですよね。

遠方の方は、自分で始めちゃうのが一番いいのかもしれません。あとはオンラインでしょうか・・・。ちょっとオンラインで継続されているコミュニティの例を僕が知らないのでこの辺はよくわかりません。

僕は横浜在住ではないのですが、Yokohama.rbによく参加しています。片道1時間以上かかりますが。

rubyにこだわらずに勉強会に参加してみるのもいいと思います。そこから得られる刺激は他では得難いものですし、人とのつながりが増えていくのはとても楽しいことです。

勉強会を探すなら、IT勉強会カレンダーをチェックです。

あとはTwitter経由で勉強会の情報を得ることが多いので、ブログなどで見かけた活発に活動されている人を片っ端からフォローするのがいいのではないでしょうか。

まとめ

思いついたことをどんどん書いていたら結構長くなってしまいましたが、少しでも参考になりましたら幸いです。
ここに書いたくらいの内容を事前に知っておけば、突然rubyの人の中に放り込まれても話が全く分からなくてぼっちというおそれは無いと思います。

あとはブログ + twitter + githubは現代のWeb系プログラマにとっては必須だと思います。たとえ趣味のプログラムだとしても。

ブログは無料のレンタルブログでかまいません。プログラマにははてなダイアリーが人気です。もうすぐ"はてなブログ"になるそうですが。

勉強会などに行って名刺を交換しても、twitterとかfacebookとかのアカウントが書いていない場合はあんまりその後の交流が持てないことが多いです。
正直、twitterアカウントはメールアドレスよりも重要かもしれません。

ということで、このエントリをきっかけに自分でWebサービスを作ってみようと思う人や勉強会やコミュニティに参加してみようという人、面白いサービスが増えたりすると嬉しいなと思います。

Yokohama.rb 第13回に参加しました

もう何回目になったのかあまり覚えていませんが参加してきました。

発表(転職とコミュニティ)

今回は発表の時間を頂いたので転職活動を通じて感じたことなどを発表してきました。
技術的なネタも一応考えてはみたのですが、転職ラッシュの今しか話せないかな、と思いこのネタです。

  • 資料
  • 動画 (miyohideさん、ありがとうございます)

質疑応答でもお話ししたのですが、決して転職という選択肢が全員にとって良いものとは限りません。現在転職を検討されている方も、ぜひ慎重にじっくりと考えて欲しいと思います。

Yokohama.rbメンバーはちょうど転職ラッシュの最中です。みなさんがよりよい仕事に就けるよう応援したいと思っています。

レシピブック読書会

この本をみんなで読み進めています。

これが予想以上に濃いんですよね。一人で読んでいると読み飛ばしてしまうようなところまで、深く掘り下げることができます。

少し読んではコードを書き、議論し、そしてまた進むという。

まさに初心者にとっても上級者にとっても面白い企画になっていると思います。

スティーブ・ジョブズの演説

追悼として、伝説のスピーチとされるスティーブ・ジョブズのスタンフォード大学での卒業式式辞をみんなで鑑賞しました。

http://www.youtube.com/watch?v=OaMT8fZpEXA

僕は今回初めてこの動画を見たのですが、「点をつなげること」、「愛と喪失」、「死について」いずれのテーマも経験に基づいた話で、非常に勇気づけられ、背中を押してもらえるような内容でした。

  • 「今日で死ぬとしたら、今日は本当にすべきことをするのか。その答えがNoである日が続くようなら、何かを変える時だ。」
  • 「他人の人生を生きないこと」

何かを決断するとき、勇気をもらえそうな言葉ですね。

ところで、転職の話題の後でこの動画を見るとうっかり転職してしまいそうな人が多発しそうです・・・。

TDDBC横浜

TDDBC横浜 にスタッフとして参加することにしました。
うちから会場まで1時間半以上かかってしまい結構遠いのですが、いつも定員オーバーでなかなか参加することのできないTDDBCに確実に参加するチャンスでもあると思いますし。

幸い業務でrspecを使用していますが、この機会にrspecの復習をしておきたいと思います。

rbenv + ruby-buildのインストール方法

rbenv, TextMateで開発環境をシンプルにしてみたでも書いたrbenvですが、最近rvmからの乗り換え先として検討している方が多いようです。

僕もあれから1ヶ月半ほど継続して使っていますが、特に困ったこともなく快適に使っています。

そこで、2011年10月5日現在の最も簡単だと思われるrbenv + ruby-buildの導入方法を書いてみようと思います。

rbenv, ruby-buildのインストール

$ brew install rbenv
$ brew install ruby-build

Homebrewから入れるのが一番簡単だと思う。

rbenvの設定

.bash_profileに以下のように書きます。

eval "$(rbenv init -)"
source ~/.rbenv/completions/rbenv.bash

if以下はタブ補完のための設定です。シェルでrbenv まで打ってタブキーを打つとサブコマンドが保管されますので便利です。

zshの人は.zshrcへ多分こんな感じ。

eval "$(rbenv init -)"
source ~/.rbenv/completions/rbenv.zsh

rubyのインストール

ここではとりあえず1.9.2-p290を入れてみます。
rbenv installコマンドはruby-buildをインストールすることによって使えるようになります。

$ rbenv install 1.9.2-p290
$ rbenv global 1.9.2-p290
$ rbenv rehash
$ ruby -v
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.1.0]

新しいバージョンのrubyや、バイナリを提供するgem(sassとか、railsとか)をインストールした後は$ rbenv rehashして下さい。そうしないとコマンドが見つかりません。

ちなみに、$ rbenv installだけ打ってエンターキーを打つとインストールできるバージョンがずらっと表示されます。

また、MacVimを使っている場合など、libruby.dylibが欲しい場合は./configure時に--enable-sharedを指定する必要があります。これは、"CONFIGURE_OPTS"という環境変数に指定することで可能となります。

$ CONFIGURE_OPTS=--enable-shared rbenv install 1.9.2-p290

簡単な使い方

$ rbenv global 1.9.3-rc1 # 使用するrubyのバージョン切り替え
$ rbenv local 1.9.3-rc1 # このディレクトリ以下で使用するrubyのバージョン切り替え
$ rbenv versions # インストールされてるrubyのバージョン一覧
$ rbenv version # 現在有効になっているrubyのバージョン

$ rbenv localするとカレントディレクトリに.rbenv-versionというテキストファイルが作られます。rvmで言う.rvmrcみたいなものですね。

公式リポジトリ

SinatraでWardenを使った認証がテストできなかった件

問題

wardenを使ってsinatraアプリを作っていたのですが、テスト時にwardenのauthenticated?などのメソッドを呼び出す箇所でenv['warden']がnilになっている旨の例外が発生し、うまくテストできませんでした。
これはcapybara-webkitやseleniumドライバを使っても同様でした。

しかし、ブラウザからアクセスするとちゃんとwardenが有効になり、意図通り認証ができます。

やってみたこと

wardenやrack/testのコードを読んだりしてみたのですが、どうにも理由がわかりませんでした。
deviseのTestHelperも見たのですが、今回の件にはあまり大きく関係しないのかなぁという感じで。
埒が明かないので、この件をエントリにまとめて有識者に助けてもらうことを期待し、検証するための小さなアプリを作ってみました。

warden_test

app.rbに、ほとんどのコードを積み込みました。
なんと、こちらのコードでは正しくテストができました。Caypbaraでcapybara-webkitやseleniumドライバを使った時も同様にちゃんと動きました。

解決

わかってみれば単純でした。以下のコードをrackup.ruに書いていたのがいけないのでした。テスト時にwardenがそもそも使われていなかったということですね。

use Warden::Manager do |manager|
  manager.default_strategies :password
  manager.failure_app = Hogehoge::App
end

まとめ

問題の切り分けのためにはちょっと面倒でも手を動かして検証しましょう。

RubyKaigi2011に行ってきた

懇親会を含めて全日程参加してきました。
セッションの様子や感想などはhttp://b.hatena.ne.jp/t/rubykaigi2011RubyKaigi2011 スペシャルレポートを見ていただくのがいいです。

ここでは自分が主体的に参加した部分と、感想などを書いてみようと思います。

!RubyKaigiで発表しました。

資料: 趣味プログラミングのすすめ

「趣味プログラミングのすすめ」というタイトルで15分、しゃべりました。

内容的には、今は個人でどんどんサービスが作れてしまう時代だしチャレンジしてみると色々返ってくるものもあって楽しいですよ、というお話です。

自分の経験を事例として、どんなきっかけで趣味でもプログラミングをするようになったのか、どうやってモチベーションを保つようにしているのか、といったことを話しました。

最後のRubyKaigiで自分の話をすることができてとてもよかったです。

Rails勉強会@東京第64回を開催しました。

@1syoさんが中心となって企画を進めてきた、これに乗っかってお手伝いをしました。

僕の担当はRails3時代の情報の調べ方について、ということで素晴らしい「Rails情報源の歩き方(前編)」に沿って、それぞれのサイトの特徴や使い方を紹介したり、ということを、僭越ながらみなさんの前に出て進行役をさせていただきました。

参加者もたくさんいましたが、ある程度みなさんの意見も聞きながらコミュニケーションできたのでは、と思っています。

また後半は飛び入りで参加して下さった@AkitaOnRailsさんから、非常に力強いメッセージをいただくことができました。

そのあたりはwiki(Rails勉強会@東京第64回)にまとめさせていただいたので、ぜひご覧ください。

初めてだけど楽しめた

実は、今回が僕にとっては初めてのRubyKaigiでした。まさに最初で最後のRubyKaigiです。

初めてだけどこんなに楽しく3日間を過ごすことができたのはyokohama.rbのメンバーをはじめとする、たくさんの仲間がいたからだと思います。
まだ数回しか行っていないし、そもそも横浜に住んでもいないし通ってもいないし、という遠慮がちょっとあって「yokohama.rbによく顔を出しています」なんていう自己紹介をしていましたが、そろそろ「yokohama.rbから来ました」と言わせていただいてもいいですよね?

もちろんこの場での出会いも素晴らしいものでした。
たまたま初日に隣り合っただけの岡山から来た学生さんと意気投合して一緒に行動したりできたのも、やっぱりrubyという共通のものを通してつながった仲間だからだと思います。

今後の課題

もっと前に出る

有名な方もたくさんいらっしゃってしかも目の前にいてお話しするチャンスもたくさんあったのに、なんか物怖じしてしまい話しかけられなかった。これは自分でも悪いところだと思っていて、でも勇気が出なくて・・・と思っていました。

最終日の夜、RejectRejectReject(?)HerokuPartyでだんさん(@dan5ya)さんからも、「なんで話しかけないのかわからない、もったいない」と言われました。だんさんの経験なども聞かせていただいて、次こそはもっと前に出て、色んな人に話しかける勇気をもらいました。
あと、「頭の良さは伝染る」というお話も良かった。すごい人の近くにいると、その人の価値観とか考え方に影響されることがあって、それが「伝染る」ということです。
「話しかけれられて嫌がる人はいないから・・・」、確かにそうですよね。やってみます。

「これ」と言える実績を作る

プロダクトでも、活動でも、「あぁ、あの@satococoaさんね!」と言われるような実績を作りたい。当面は発表でもやったような趣味プログラミングを、もう少し技術ドリブンではなくて、使う人を少し幸せにできるようなサービスを作りたいなぁと思います。

あとは、最近立ち上げたデザイナー向けプログラム部を盛り上げていけるよう頑張りたいです。

Rails勉強会@東京第63回に参加

Rails勉強会@東京第63回に参加してきました。

今日のセッションは以下のとおり。

  • 前 CoffeeScriptについて(全体)

    1. テストについて
    2. Rails 3.1について
    1. PaaSについて
    2. Rails開発のTipsなど

CoffeeScript

まずはセッション開始前にjs2coffeeというNodeのライブラリを教えてもらいました。
始めは普通に.coffeeを.jsにするものだと勘違いし、会話が成り立っていませんでした。すみません。逆なんですね。

セッションではCoffeeScriptをインストールし、公式サイトを見ながら実際に打ち込んでテストをしました。

MacでもWindowsでも、Nodeを入れなくてもruby-coffee-scriptを使えばexecjsが適切なJavaScriptの実行系を探して、CoffeeScriptにコンパイルできるみたいです。

$ gem install coffee-script

この場合、コマンドラインからcoffee -> jsにするにはそれ用のスクリプトを作る必要があります。

セッションではそれぞれnodeのcoffeeコマンドで実行したり、公式サイトのTRY COFFEESCRIPTで実行したりして試しました。

-bオプションを付けるのと付けないのとで、まずはコンパイルのされ方が違うことを確認。-bオプションを付けないと、全体が無名関数に囲まれます。

$ coffee -c hello.coffee
$ coffee -bc hello.coffee

途中までは上から順番に進めていっていたのですが、「CoffeeScriptで便利なのはClassを使えるところ」という意見があり、Classを作ってみることに。

class Animal
  constructor: (@name) ->
  move: (meters) ->
    console.log @name + ' moved ' + meters + 'm.'


class Snake extends Animal
  move: ->
    console.log "Slithering..."
    super 5

sam = new Snake "Sammy the Python"
sam.move()

これでクラスの継承。簡潔ですね。@nameはjsにするとthis.nameと解釈されます。
(ずっと勘違いして今まで@.nameとわざわざ書いていたことにこのとき気付きました。)

そして、次にクラスメソッドを試してみたところで問題が発生しました。
クラスメソッドのあるクラスを継承した場合、TRY COFFEESCRIPTの実行結果とローカルでcoffeeコマンドで実行した結果が違った・・・と思って今やり直したら、同じ結果になりました。
バージョンの違いか、何か間違っていたのか、ちょっと原因はわかりませんが、以下のコードはどちらでも意図通り動きます。

class Animal
  constructor: (@name) ->
  @classmethod: () ->
    console.log "Animal's classmethod"

class Snake extends Animal
  @classmethod: () ->
    console.log "Snake's classmethod"

Animal.classmethod() #=> Animal's classmethod
Snake.classmethod()  #=> Snake's classmethod

あとは便利だなーと思ったのは=>でしょうか。

Account = (customer, cart) ->
  @customer = customer
  @cart = cart

  $('.shopping_cart').bind 'click', (event) =>
    @customer.purchase @cart

JSだと、'click'にbindするときに、実行時のthisがAccountのオブジェクト自体にならないために通常 var self = this; するところを、=>を使うと自動的に定義時のthisが実行時にもthisとして参照できるようなコードを生成してくれます。

あと-wオプションではファイル単位ではなくディレクトリを指定することもできることを今日知りました。便利。

しかし、これを変換したjsをブラウザで実行させ、デバッグさせるとなると大変です。何かいい方法はないのでしょうか?
しかもrails3.1で使うと本番環境ではさらにuglifierによる圧縮もかかります。

Rails 3.1

中盤のセッションはRails 3.1の話題の方へ参加しました。

とりあえずrails newしてみていきなり自動的にbundleが始まり、意図せずgemsetも分けていないシステムに全gemが入っていってしまう事件を目撃しました。

ちなみに、bundleを自動的に実行させたくないときは--skip-bundleオプションを付けます。

$ rails new blog --skip-bundle

その後はapp/assets/javascripts/application.jsを見て、実際にcoffeeを書いてみて、Sprocketsをちょっと調べました。

次にHTTP Streamingを調べるためにASCIIcasts266: HTTPストリーミングを見ながら実際にcurlでコマンドを打って実験してみました。
使いどころとしては、CSVをダウンロードさせる、とかXMLをダウンロードさせる、とかかなぁ・・・という話。

次にIdentity Mapの動きをrails consoleで試し、最後にtest/unitの結果に色がついて綺麗になったところまで確認して終わり。

PaaSについて

3コマ目のセッションはPaaSについて語りました。

セッション参加者が使ったことのあるPaaSは以下のとおりで、それぞれ使ってみた感想や特徴などを話しました。

  • heroku
  • DuoStack
  • DotCloud
  • CloudFoundry
  • fluxflex(微妙だったという話)

DuoStackはDotCloudに買収され、もう新規アプリは作れなくなっていました。
herokuは課金体系が変わり、1dyno hourという単位で課金されますが、1dyno or 1workerを1ヶ月フルに動かす分+ちょっとが無料で使用できる範囲となっています。あと、CedarというstackでNodeも動くようになっています。

最後にherokuを使う上で便利なadd-onについて話しました。

  • Hoptoad: 業務で使うなら入れるべき。JSのエラーまで通知してくれる。
  • StillAlive: 公式サイトのビデオは必見。Cucumberみたいな感じに実行する操作を定義できます。

まとめ

前回より人数は少なかったみたいですが、その分実践的な話や具体的な話ができたり、わいわいと3.1を触ったりできて楽しかったです。
また、いつもながら場所を提供していただいている永和システムマネジメント様に感謝です。

また参加したいと思います。ありがとうございました。

HerokuでRails3.1(RC1)を動かす方法

Yokohama.rb 第9回に参加してきました。
その場でRails3.1をherokuで動かそうというニーズがあったので、ざっとまとめます。

ポイント(2011-06-05版)

  • まだ3.1.0はrcなので、rvmのgemset機能を使っておこう
  • pgとtherubyracer-herokuをGemfileの:productionに追加する
  • rakeは現時点では0.8.7をバージョン指定しておくほうが無難
  • herokuのstackをbamboo-mri-1.9.2を使っておこう

手順

Rails 3.1.0 RC1のインストール&アプリ生成
$ rvm gemset create rails31
$ rvm use 1.9.2@rails31 # もちろんrubyは1.9.2使ってますよね?
$ gem install rails --pre --version 3.1.0.rc1
$ rails new blog # とりあえずblogで

もしターミナルを閉じてしまうとまたgemsetがデフォルトのものを使うように戻ってしまうのですが、プロジェクトのルートに.rvmrcを置いておくと、毎回 rvm use を打つ必要はありません。

.rvmrcの中身

rvm use 1.9.2@rails31

これで、プロジェクトのディレクトリにcdしたときに、自動的にgemsetが切り替わります。

このへんで一回gitにコミットしておきましょう。

$ git init
$ git add .
$ git commit -m 'initial commit'
herokuで動かすために必要なgemを追加する

Gemfileはこんな感じになります。

source 'http://rubygems.org'

gem 'rails', '3.1.0.rc1'
gem 'sass'
gem 'coffee-script'
gem 'uglifier'
gem 'jquery-rails'
gem 'rake', '0.8.7'

group :production do
  gem 'pg'
  gem 'therubyracer-heroku'
end

group :development do
  gem 'sqlite3'
end

group :test do
  # Pretty printed test output
  gem 'turn', :require => false
end

さてbundleしますが、普通にbundleと打つと、:productionに指定してあるpgやtherubyracer-herokuもインストールしようとしてしまいます。
ローカルにPostgreSQLが入っているのならいいと思いますが、そうではない場合は:productionのgemを除外してインストールすることができます。

$ bundle --without production
$ bundle update rake # rakeのバージョンが0.9.1が入っているので、これを打つように言われる
$ git commit -am 'modify Gemfile'
適当なアプリをでっち上げる
$ rails generate scaffold post title:string body:text
$ bundle exec rake db:migrate
$ rails server  # 一応ローカルでも動作確認
$ git add .
$ git commit -m 'scaffold post'
herokuにデプロイしよう
$ gem install heroku
$ heroku create [適当なアプリ名] --stack bamboo-mri-1.9.2
$ git push heroku master
$ heroku rake db:migrate
$ heroku open

これで無事にデプロイできたはずです。お疲れさまでした。

heroku createの行の--stackオプションですが、本当なら6/1以降はデフォルトでbamboo-mri-1.9.2になるそうです。
Yokohama.rbで試したところまだ1.8.7の方で作られてしまいましたので、明示的に指定しています。

rakeのあたりとかちょっと気持ち悪いですが、もっとうまい方法があれば教えてください。
あとはRC1版で試していますので、バージョンが変わると上記の方法でできなくなるかもしれませんのでご注意ください。

大江戸Ruby会議に参加してきました

大江戸Ruby会議に参加してきました。
少し時間が経ってしまいましたが、感想を書いておこうと思います。

@a_matsudaさんの基調講演では「コミュニティ」について考えさせるところがありました。

どの発表も具体的でたくさん学ぶことがあったのですが、その基調講演を聞いて色々と考えることがあったので自分なりに書いてみようと思います。

冒頭でAsakusa.rbについて松田さんがおっしゃっていたのは以下のようなこと。

  • Asakusa.rbは勉強会ではなく、セミナーでもない。
  • 「お客様」ではなく「仲間」に来て欲しい
  • もくもく会でもないので喋って欲しい

そしてAsakusa.rbの目的は「Rubyを良くしたい。」ということ。

Rubyという言語は好きだし、もっとよくなってほしい。
(現状で特に不満があるわけではなく、具体的にどこが、というわけではないですが。)
それに対して自分は何が出来るのか、ということをぼんやりと考えました。

外の世界に出ていくこと

去年の半ば頃から、僕はなるべく積極的に外に出ていこうと決め、IT勉強会カレンダーなどを見ては興味のあるものに参加するようにしています。
何か自分も貢献したいな、と思いつつも結局「お客様」レベルの参加しかできないことが多々ありますが。

それまで外に出ていけなかったのには自分の中では理由があって、(今となっては後悔しているのですが。)
これは錯覚なのかもしれませんが、自分とそういったコミュニティやら勉強会やらの間になんか隔たりがあるような気がしていたのです。
ましてや、Ruby界隈の集まりに行くとすぐにWeb上の有名人やいわゆるすごい人がたくさんいる。
そんな中では「仕事でRubyを使っていない」ということすらひとつのコンプレックスでした。

未だにSCMすら使わず、テストも書かないというレガシー真っ只中の自分の仕事の現状と、やれソーシャルだ、アジャイルだ、クラウドだと言っている環境との間に大きな隔たりを感じると同時に、「違う世界なんだ」と半ば諦めて心が折れそうになっていました。

でも勇気を持って一歩会社の外に踏み出してみたら、レガシーな環境に勇敢に立ち向かいつつもきちんとプログラミングを楽しんでいる人がたくさんいました。
たしかに、例えばRailsを業務で使っているような方と趣味のみでちょこちょこ手を出している程度の自分とでは全然理解のレベルも違うし問題意識も違う。
でもプログラミングが好きだ、ということはみんな共通だし意外と話も合う。
「会社」という狭い世界を超えると本当に楽しいことがあちこちに転がっている。

こういう体験ができることをこうやってブログなり会社なりで伝えることで、プログラミングを一緒に楽しめる仲間が増えたら嬉しいと思うし、そうやってRuby好きを増やすことも自分にできるささやかな貢献なのかなぁ・・・と思っています。
本当にささやかで笑っちゃいますが、もっと楽しんでプログラミングしたい、と思います。

全然まとまりませんし、あまり感想にもなっていませんがこんなところで。

InstagramのReal-time APIを使ってみた

Tokyo Real-time Photosというアプリを公開しました。
Nekostagramに代表される、Instagram系サービスが人気です。やや波に乗り遅れた感はありますが、僕も何か作ってみようと思い立ちチャレンジしました。

これは何?

Instagramで東京付近の写真がアップされると、リアルタイムで画面に表示されるだけのアプリです。具体的には以下の青丸の範囲です。(未公開の管理側です。)
InstagramのReal-timeAPIを使っています。

技術的には?

信頼のsinatra + Herokuで作っています。リアルタイムに写真が通知される部分はPusherで、Redisをキャッシュ + DB用途で使っています。
こういった外部APIを使った簡易的なサービスにはsinatraは最適ですね。
ソースコードはこちら:https://github.com/satococoa/Tokyo-Real-time-Photos

Real-time APIについて

まずInstagramのReal-time APIを僕が使った範囲でちょっと説明します。
利用手順としては3ステップになります。
  1. 条件を指定して購読申し込みを行う
  2. 購読申し込みに対してInstagramから確認を受ける
  3. Instagramからの通知を受け取る
それぞれコードを見ながらいきます。
1. 条件を指定して購読申し込みを行う
post '/admin/subscriptions' do
  require_admin # ここではとりあえず無視してOKです。
  client = Instagram.client(:access_token => session[:access_token])
  obj = client.create_subscription(:client_id => Instagram.options[:client_id],
                                   :client_secret => Instagram.options[:client_secret],
                                   :object => 'geography',
                                   :aspect => 'media',
                                   :lat => params[:lat],
                                   :lng => params[:lng],
                                   :radius => 5000,
                                   :callback_url => subscript_url)
  # subscript_urlは更新の通知を受け取るURLです。
  data = {:lat => params[:lat], :lng => params[:lng], :radius => 5000}
  REDIS.set("subscription:#{obj['object_id']}", data.to_json)
  # create_subscriptionの返り値からobject_idを受け取り、緯度・経度・半径の情報と一緒に保存
  obj
end
これは管理画面で地図上の点をクリックしたときにAjaxで呼び出されるコードです。
create_subscriptionメソッドを使って、クリックした点を中心とした半径5km圏内の更新に対して購読を申し込みます。するとInstagramから購読申し込みに対しての確認アクセスが来ますので、それに答えてあげるのが次のコードです。
2. 購読申し込みに対してInstagramから確認を受ける
get '/subscription/callback' do
  params[:'hub.challenge']
end
(本当はそのアクセスがほんとにInstagramから来ているのか、ちゃんと検証すべきでしょうけれども、やってません;;)
さきほど:callback_urlで指定したURLにInstagramからGETのアクセスが来ます。そしたらパラメータのhub.challengeをそのまま返してあげてください。これで購読完了です。

Herokuでやる方へ注意:この際、先ほどの購読申し込みのPOSTリクエストが、購読確認のGETリクエストに対してレスポンスを返すまで終了しません。つまり、同時に2アクセスは最低さばかないといけない、ということです。
仕方ないので、僕はこのときだけDynoを2個にしました。ハマりました。
3. Instagramからの通知を受け取る
post '/subscription/callback' do
  #略
end
略し過ぎでごめんなさい。でも普通にcallback_urlにしたURLにPOSTのリクエストが来るだけです。
ただ、ちょっと注意したいのがここで実際に写真データが送られてくるわけではないことです。

購読申し込みが成功すると、create_subscriptionメソッドは:object_idを含むオブジェクトを返してきます。
そして、実際に写真がUPされてアプリ側にInstagramから通知が来るときには、その:object_idを含むオブジェクトを送ってくるので、それをもとにInstagramからAPIを使って画像を持ってくる必要があります。
(・・・ですよね、多分。しっかり調べた訳じゃないのでちょっと自信がないのです。)

ということで、詳しくは github上のコードを参考にしてみてください。
https://github.com/satococoa/Tokyo-Real-time-Photos

最後に制限事項

Herokuからアドオンとして利用できるPusherを使っていますが、これが1日に1万回までしかリクエストを受け付けてくれません。
時間帯によって写真がアップされる頻度が違っているためによくわかりませんが、もしかすると簡単に1万回は超えてしまうかもしれません。
自動で写真が表示されなくなったら察してください。

時間帯によって、一定枚数の写真をキャッシュすればいいのかもしれませんが、とりあえずはInstagramからPOSTが来るたびにリアルタイムに通知していってみようかと思います。

以上です。お楽しみいただけると幸いです!

CloudFrontを使ってみた

昨日のコードに機能追加をし、CloudFrontを使うようにしてみました。
CF = RightAws::AcfInterface.new(ACCESS, SECRET)
CF.create_distribution(get_domain_for_bucket(bucket), "distribution for #{bucket.name}"
ハマったのは2行目の第一引数。バケットをap-southeast-1のリージョンに作ったため、てっきりmybucket.s3-ap-southeast-1.amazonaws.comみたいなドメインを指定するのかと思っていたのですが、mybucket.s3.amazonaws.comの形式で指定しないと作れませんでした。
get_domain_for_bucketはbucket名にs3.amazonaws.comを付けてるだけのメソッドです。

あとは以下のようなコードでディストリビューションを選択し、そっちのドメインから配信するようにしてやればOKです。
dists = CF.list_distributions
#=> [{:aws_id=>"nnnnnnnnnnnnnn",
  :status=>"Deployed",
  :last_modified_time=>"2011-03-01T14:02:00.543Z",
  :domain_name=>"xxxxxxxxxxxxx.cloudfront.net",
  :origin=>"mybucket.s3.amazonaws.com",
  :comment=>"distribution for mybucket",
:enabled=>true}, {:aws_id=>"nnnnnnnnnnnnnn", :status=>"Deployed", :last_modified_time=>"2011-03-01T14:02:03.330Z", :domain_name=>"xxxxxxxxxxxxx.cloudfront.net", :origin=>"mybucket-thumb.s3.amazonaws.com", :comment=>"distribution for mybucket-thumb",
:enabled=>true}]

def get_distribution_for_bucket(bucket, dists)
  dists.detect{|dist| dist[:origin] =~ /#{bucket.name}.+/}
end
@bucket       = S3.bucket(bucket_name)
thumbs_bucket = S3.bucket(bucket_name+'-thumb')
dists         = CF.list_distributions
@dist         = get_distribution_for_bucket(@bucket, dists)
@thumbs_dist  = get_distribution_for_bucket(thumbs_bucket, dists)
# "http://#{@dist[:domain_name]}/#{key.name}"
こんな感じです。
これだけで世界中に効率よくコンテンツを配れるというのはすごいですね。