Posted by irohiroki
Sun, 03 Jun 2012 06:32:00 GMT
みなとRuby会議01に参加してきました。
一般的な講演の他に、ペアプロのセッションがあるという面白いRuby会議だったのですが、実はペアプロは初めてだったので気づいたことを書いてみます。
ペアプロの相手は@hibariyaさんで、僕はナビゲーターしかしなかったんですが、それでも多くのことがわかりました。
2人の役割分担は車の運転と同じ
初めての道を運転するとき、ナビがあった方が楽ですよね。
そして、コーディングでは初めてのものを実装することが多いんです。
誰かが案内してくれた方がずっと楽なはずです。
ナビゲーターは、ドライバーより多くのことを考えられます。
なぜならタイピングに脳を使ってないから。
次に何をタイプするか、近道はないか常に考えていられます。
この辺の雰囲気はXPエクストリーム・プログラミング入門
に書かれていた通りでした。
(他にもコーディングの最前線で使うべき戦術が丁寧に書かれていて、おすすめの本です。)
考えるだけの時間がなくなる
「考えるだけの時間」とは、話していない、聞いていない、タイプもしていない時間です。
僕は一人でコーディングするとき比較的考え過ぎる方だと自覚していて、減らしたいと思っているんですが、ペアプロをしてれば圧倒的に少なくなりそうです。
それはもちろん、ナビゲーターが考えることを引き受けるからという理由もあるのですが、もっと重要な理由があると思います。
一人で考えてて一番ダメだと思うのは、情報が十分でない状況で複数のことを比較しているときです。
そういう時やるべきなのは、情報を得るためにどれかを選択して実行することです。
ところが同時に、手戻りをなるべく減らしたいという動機があるため、実行せずに情報を得ようとしてしまうのです。
ペアプロでは、ナビゲーターはタイプしないので、手戻りの考慮から一歩引くことができます。
一方ドライバーは、自分で決断できなくても、ナビゲーターが指示したことなら実行しやすいでしょう。
このようにペアプロならば、ナビゲーター/ドライバーのどちらであっても考える時間を減らすことになります。
人のマシンを使うのは非現実的
今日の会場はネットワークが貧弱だったため、ネットを介してソースコードを共有せずに、1台のマシンを交代で使うという方針でした。
でもそれは非現実的でした。
僕は日本語キーボードを使ってるんですが、ペアを組んだ@hibariyaさんのマシンはUSキーボードでした。
また、GNU screenのエスケープキーが違いました。
おそらくエディタの設定は更なる乖離を見せてくれたでしょうが、もう確認はしませんでした。
他人のマシンで快適にコーディングなんてできないと思います。
ペアプロするなら常にドライバーの人のマシンを2人で見るべきだと思いました。
というわけで、ナビゲーターしかしなかったものの、たくさんの気づきのあったペアプロでした。
ペアプロが向くケース、向かないケースも少しわかりました。
ペアを組んでくださった@hibariyaさん、ありがとうございました。
また、みなとRuby会議01を運営してくださったYokohama.rbのみなさん、ありがとうございました。
みなさんお疲れ様でした。
Posted in Meetup | no trackbacks
Posted by irohiroki
Wed, 18 Jan 2012 23:10:00 GMT
去年の9月からKRAYで働いているのですが、そちらにエントリ書きました。
RailsのデプロイとUnicornのトラブルシューティング | KRAY Inc
UnicornのしくみはUnixらしくてきれいです。よかったら読んでみてください。
Posted in Tech | no trackbacks
Posted by irohiroki
Mon, 25 Jul 2011 16:54:00 GMT
お祭り騒ぎしてるだけのつもりだったのに、Twitterとか見ると“スタッフのみなさん、ありがとうございました”とか書いてあるんですよ。これは丸儲けなんじゃないかって
というのは私が最終日のチェックアウト(区切りをつけるための一言)で言ったセリフだ。RubyKaigi 2011に当日スタッフとして参加し、3日間、朝から夜まで働き、体力は尽きたが、そんなことはどうでもいいくらい楽しい思いをさせてもらった。
RubyKaigi 2011は7月16日から18日までの3日間、練馬文化センターで開催され、2つのホールで合計47のセッションと、無数のライトニングトークが行われた。参加者は約1,000人で、その中には海外から来た人も多い。しかし私の記憶には、そんな数では表し切れないとてつもなく強いインパクトを残した。
RubyKaigiは完全に非日常的な体験だ(あんなものが日常的にあってたまるか)。人の体験には、一緒に過ごす人が大きな影響を与えるように思う。そしてRubyKaigi中は普段とは全く違う人たちと過ごした。実行委員と当日スタッフのメンバーを合わせて約50人。主にネットを介してしか知らず、半分以上の人が初対面。そんな人たちと、初めての場所で、1,000人のお客さんを迎えるために働く。実行委員長が言っていたが、RubyKaigiは毎回違ったものになるので、毎回“初めてのRubyKaigi"であり、何が起こるか分からないのだそうだ。つまり、参加している全員にとってRubyKaigi 2011は新しい体験だった。
豪華なセッションの数々も印象的だった。基調講演をしたMatz、たこやき仮面、角谷さん、それから笹田さんやyharaさんをはじめとしたコミッター陣、wycatsやdrbrainといった海外のgeekたち、井上さんや朝里さんなどの海外で活躍する日本人Rubyist… 全員は挙げないが、魅力的なセッションが朝から晩まで続く目の眩むようなタイムテーブルだった。スタッフだったので1/4くらいしか生で見てないが、記憶に焼き付くような話がいくつもあった。我々スタッフはそれをホストし、1,000人の人たちそれぞれに、何かしら持って帰ってもらえたのではないかと思う。
いくら言葉を尽くしても足りないが、僕にとってRubyKaigiは素晴らしい体験だった。大変と言えば大変だが、もう一度やりたいと思う。でも知っての通り今回で“日本RubyKaigi”はおしまいだ。やりたければ、自分なりの形を見つけて自分でやらなければならない。それが“最後のRubyKaigi”の意義の一つであり、角谷さんの「答え合わせしませんか」は、それを促すメッセージだ。
RubyKaigiとは何なんだろうかと思う。なぜあんなに多くの人に支持されるのか。同じ会場で同じ人を集めて同じセッションを開けばRubyKaigiができるのか。ここで分析したり持論を展開したりはしないが、RubyKaigiをRubyKaigiたらしめるエッセンスがある。それを探求しつつ、自分のまわりに“答え”を作っていきたい。
RubyKaigiは楽しく、活気があり、出会いがあって、私を啓蒙してくれる。自分のまわりのものがもっとRubyKaigiっぽかったら素敵だと思う。例えば自分の会社やプロジェクトがもっとRubyKaigiっぽかったら。会社やプロジェクトを大好きになると思う。自分だけでなく、他の人も大好きになってくれるものならもっといい。そのためにはどうすればいいか?何をどうすれば、RubyKaigiっぽくなるのか?それを探求しながら自分のまわりに広めていきたい。
Posted in Meetup | Tags RubyKaigi | no trackbacks
Posted by irohiroki
Thu, 16 Jun 2011 06:25:00 GMT
Rack middlewareで発生する例外とは
アプリケーションで発生する例外を捕捉し、適切な処理をするのは一般的なことだと思います。コントローラの中で発生する例外はbegin rescueで囲ったり、rescue_fromを使えば捕捉できますが、Rack middlewareで発生する例外はどうでしょうか?
例えばMySQLを使っていてデータベースサーバに接続できない場合、ActiveRecord::ConnectionAdapters::ConnectionManagementというmiddlewareからMysql2::Errorが発生します。
ActiveRecord::ConnectionAdapters::ConnectionManagementはrake middlewareすると10番目に出てきます。
$ rake middleware
use ActionDispatch::Static
use Rack::Lock
use ActiveSupport::Cache::Strategy::LocalCache
use Rack::Runtime
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::RemoteIp
use Rack::Sendfile
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::MethodOverride
use ActionDispatch::Head
use ActionDispatch::BestStandardsSupport
run MyApp::Application.routes
ウェブサーバはこの上にあり、自分のアプリケーションは一番下です。例外はrescueしなければ上へ上がって行きます。つまり、どうやってもアプリケーションではrescueできません。
ではどうハンドリングすればいいでしょうか?
ActionDispatch::ShowExceptionsを使う?
スタックを見ると上から6番目にActionDispatch::ShowExceptionsというのがあります。ソースを見ると、例外のクラス名をステータスコードにマップしていることがわかります。
例えば、Mysql2::Errorを507 (Insufficient Storage)にマップするだけなら、config/application.rbに下の行を追加し、
ActionDispatch::ShowExceptions.rescue_responses['Mysql2::Error'] = :insufficient_storage
表示したいページをpublic/507.htmlとして置いておけば済みます。
しかしMysql2::Errorの原因が全てInsufficient Storageではありませんし、MySQLが無関係なInsufficient Storageも有りうるので、適切な措置とは言えません。
ActionDispatch::Rescue to the... you know, rescue!!
Rack middlewareで発生した例外はActionDispatch::Rescueというmiddlewareで捕捉できます。ActionDispatch::ShowExceptionsと違い、ActionDispatch::Rescueは例外クラスに対してハンドリングするRackアプリケーションを指定できます。
例えば、application.rbに下のように追加すれば、Mysql2::Errorに対して「Database failure.」と表示できます。
config.middleware.insert_before ActiveRecord::ConnectionAdapters::ConnectionManagement, ActionDispatch::Rescue do
rescue_from Mysql2::Error, lambda {|env| [500, {'Content-Type' => 'text/plain'}, 'Database failure.'] }
end
ステータスコードは500 (Internal Server Error)で十分でしょう。ポイントは、レスポンスボディとして任意の内容を返せることです。任意の内容を返せるということは、ユーザに適切なメッセージを見せたり、JavaScriptのフロントエンドにJSONなどで適切なステータスを返したりできるということです。
なお、上のrescue_fromはActionDispatch::Rescue#rescue_fromで、コントローラのマクロ風rescue_fromとは別物です。
application.rbに書きたくない?
しかし、前出の
lambda {|env| [500, {'Content-Type' => 'text/plain'}, 'Database failure.'] }
はapplication.rbに書くにはちょっと生々しい印象です。もっとコードらしい場所へ移動するにはどうしたらいいでしょうか。
ActionDispatch::Rescue#rescue_fromの第2引数はRackアプリケーションですから、Rackアプリケーションとして振舞うクラスを指定してやれば済みます。例えばActionController::Metalを継承すればそういうクラスを簡単に作れます。
class DatabaseFailure < ActionController::Metal
def self.call(env)
action(:respond).call(env)
end
def respond
self.status = 500
self.content_type = 'text/plain'
self.response_body = 'Database failure.'
end
end
application.rbには下のようになります。
config.middleware.insert_before ActiveRecord::ConnectionAdapters::ConnectionManagement, ActionDispatch::Rescue do
rescue_from Mysql2::Error, DatabaseFailure
end
Posted in Tech | Tags rack | no trackbacks
Posted by irohiroki
Mon, 11 Apr 2011 22:10:00 GMT
大江戸Ruby会議01に参加してきましたので、そこで感じたこと、考えたことなどを、コミュニティへの感謝を込めて書き記したいと思います。
会場は深川江戸資料館のホールで、広すぎず狭すぎず、ちょうどよい大きさだと思いました。もちろんもっと大きな会場ならさらに多くの人が参加できますが、雰囲気が変わってしまいそうなので、開催規模としてちょうど良かったのではないかと。近くには隅田川の支流が流れ、河畔の桜並木が満開でした。
ホールは地下だったのですが、ユナイテッド・デザインワークスによる無線LANが設営されているという周到さでした。
最初の基調講演は松田明さんによる「100.times { Asakusa.rb.meetup! }」で、Asakusa.rbの趣旨や活動、歴史などが紹介されました。
印象に残ったのは「Rubyを良くしたい」というAsakusa.rb結成、活動の動機でした。この言葉は一見簡単なようで実は意味がわからなくて、というのはRubyは言語であってツールですが、別にCRubyにパッチを送るとかいう意味ではなさそうだからです。確かにAsakusa.rbにはコミッタが参加していますが、松田さん自身はそういう活動はしてません(よね?)
ではどういう意味かというと、もちろん松田さんにお聞きすれば答が返ってくるでしょうが、自分なりの解釈でAsakusa.rbに参加するのも楽しいように思えるんですよね。
例えばRubyを使うことは、Rubyの応用事例を増やして信頼度を上げるでしょうから、Rubyを良くすることになりそうです。Gemを作ったりすればもっと直接的に貢献できるでしょう。
さらに「Ruby」に「Rubyコミュニティ」を含むと解釈すると、範囲は大きく広がります。「Rubyコミュニティを良くする」というのはもう本当にいろいろな解釈がありそうですが、書くと野暮になりそうだし、探求を続けていきたい領域なのでここには書きません。
結局、「Rubyを良くしたい」の解釈は様々に可能ですが、いずれにしても自分以外の誰かに利することなので、「あなたを幸せにしたい(Rubyを通して)」ぐらいに考えておいてもいいのではないでしょうか。いずれにしても、僕はこの基調講演を聞いて、Asakusa.rbに参加してRubyを良くしたい(Rubyを良くすることを探求したい)という思いを強くし、参加する決心をしたのでした。
続いて笹田さんの基調講演と6人のAsakusa.rbメンバーによるNinja Talk (Lightning Talk)がありました。
他の言語の場合は知らないんですが、RubyのLightning Talkはデータを見せるものよりストーリーを語るものが多い印象です。自分が通信技術の会社で「◯◯プロトコルに☓☓機能を加えて受信特性を3 dB改善」みたいな発表ばかり見ていたせいかもしれませんが、RubyのLightning Talkはカジュアルで、感情に訴えてくるところが見てて楽しいですね(そうでない、データを見せるものももちろんありますが)。Regional Ruby会議は学会ではなく、交流会の意味合いが強いので、そういう発表の方が理にかなっているし、モチベーションの源になったりします。
個々の発表の感想は省きますが、今日も6人のNinjaに楽しませていただきました。ありがとうございました。
懇親会は桜鍋の店で、珍しい、美味しい料理をいただきました。よくある飲み会の大皿料理でなく、コース料理だったのも嬉しかった。また、座敷だったので人が移動しやすいのも良かったんではないでしょうか(実際には僕はチキンなので移動せず、移動してくる人を待ち構えていた)。ただ僕は体が大きいので、席が狭いのだけが少し辛かったんですが。
周りには左手側から@tyabeさん、@konk303さん、@nahiさん、@junyaさん、@jugyoさんという席。最初にnahiさんのhttpclientの話から、Railsのthreadsafe!関連の話へ。この辺は実はよくわからないので、優先順位の高いものが終わったら調べ直そうと思います。
そのうち(よく聞いてなかったんですが)Ruby 1.8.7でGCが解放したメモリをOSに返せないのかという話になったようで、@nahiさんが@shyouheiさんのところへ。"そういう研究もあるが、閉じた組織がやってるので状況はわからない"という回答をもらってきました。こういう風に、リアルなユーザの要望がその場でメンテナに届いて回答が返ってくるのが面白い。さすがAsakusa.rbです。
途中、角谷さんに社内でやった『アジャイルな見積もりと計画づくり』読書会の話をできたのが嬉しかったんですが、あまりに個人的なので省略。
その他にもリアルにRubyで商用サービスを動かしてる人たちから、JavaScriptのテストの方針や、負荷とDBの勘所の話を聞くことができました。自分はいつも職場でたった一人のRubyistとして仕事をしていて、またコンシュマー向けのアプリをリリースしたこともなく、レスポンスのほとんどない世界で漠然とした孤独を感じていました。でも懇親会で話を聞くうち、自分が作ったものを公開すれば必ず見る人がいる、使う人がいる、もしかしたら喜ぶ人もいると思えるようになってきました。これは仕事以外で開発をする上でとても大きなモチベーションになります。懇親会で話を聞かせてくれた方、大江戸Ruby会議と懇親会を開催してくれた方には心から感謝します。ありがとうございました!
Posted in Meetup | Tags meetup, Ruby | no trackbacks
Posted by irohiroki
Tue, 22 Mar 2011 22:25:00 GMT
MacにRVMでRuby 1.9.2をインストールしたとき、irbなどのReadlineのプロンプトに日本語を入力すると「???」に化けて、そのままEnterするとinvalid multibyte charなどのエラーになる問題の解決方法。
Bug #550によると、MacではGNU readlineの代わりにEditline Libraryが使われているそうで、GNU readlineを使えば解決するらしい。
RVMには簡単にGNU readlineを導入する機能があって、Rubyをインストールした後に修正する手順は下の通り(追記:一度Rubyを消さないとうまく行かないので修正。リンク先の丸写しです)。
rvm package install readline
rvm remove 1.9.2
rvm install 1.9.2 --with-readline-dir=$rvm_path/usr
cd $HOME/.rvm/src/ruby-1.9.2-p180/ext/readline
ruby extconf.rb -- --with-readline-dir="$HOME/.rvm/usr"
make install
なお、2行目のruby-1.9.2-p180の部分はインストールしたRubyのバージョンに合わせて変えてください。
追記
GNU readlineにしたら、Readline.refresh_lineがNotImplementedErrorになりました。refresh_lineを使う場合には向きませんね。
Posted in Tech | Tags irb, rvm, tips | no trackbacks
Posted by irohiroki
Tue, 08 Mar 2011 09:05:00 GMT
RSpec勉強会@万葉で発表してきたので、資料を公開します。
RSpecを2ヶ月くらい使って気づいた事と分からない事
資料の22ページで、subjectのためにdescribeを切ることについて「議論ありそう」と書いたんですが、やっぱり@ukstudioさんからツッコまれました。
曰く、describeは振る舞いの主体を表すもので、処理の結果を指すものではないでしょうとのこと(と理解した)。確かにそうですね。
しかし同じcontextでsubjectを変えると書きやすくなる場合もやっぱりあって、この問題はまだまだ楽しめそうです。
Posted in Tech | Tags RSpec, tips | no trackbacks
Posted by irohiroki
Tue, 08 Feb 2011 13:16:00 GMT
Quick link to a sample app.
Autotestはテスト駆動開発において欠かせないツールです。しかし、特にRuby 1.9ではRspecの起動の遅く、イライラしている人も多いでしょう。
Rspecの起動を早くするツールにSporkがありますが、以下のような問題があります:
-
製品コードを更新してもリロードしてくれない(ぇ
-
ruby-debugが使えない
このエントリではこれらの問題を解決していきます。目指すのは次のような環境です:
-
appの下はもちろん、configの下を更新した場合もリロードしてテストしてくれる
-
製品コードでもテストコードでも、debuggerと書いたらruby-debugが使える
Spork
まずはベースの環境から作りましょう。なお、ここで使うのはMac上のRails 3.0.3とRuby 1.9.2です。
gem install rails
rails new my_app
最初にRSpecとautotest、sporkを入れるために、Gemfileに以下の行を加えます。
gem 'rspec-rails'
gem 'autotest-rails'
gem 'spork'
Gemfileを編集したらbundleしておきます。
bundle
RSpecをインストールします:
rails g rspec:install
Sporkに必要な準備をします:
spork --bootstrap
ここで、表示される指示に従ってspec/spec_helper.rbを編集します。下のようにしておけばよいでしょう。
require 'rubygems'
require 'spork'
Spork.prefork do
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.mock_with :rspec
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
end
end
Spork.each_run do
end
またSporkを有効にするため、rspec:installによって生成された.rspecファイルに--drbを加えておきます。
--color --drb
これで素のAutotestとSporkの環境はできました。適当なコードをscaffoldして試してみてもいいでしょう。
rails g scaffold user name:string
rake db:migrate RAILS_ENV=test
sporkを起動し、別のターミナルでautotestも実行します。
spork
autotest
さらに別のターミナルでテストコードを失敗するように修正するとすぐさまautotestが赤くなります。しかし、製品コードを壊した場合、テストは走りますが緑のままです。
リロードさせる
製品コードのリロードは、実は次の2つの問題に分けられます。
-
app下のファイルを修正した時
-
それ以外
1はRuby on Rails Tutorial: Learn Rails by Example | Ruby on Rails 3 Tutorial book and screencasts | Static Pagesに回避方法が載っています。まず下のようにspec/spec_helper.rbのRSpec.configureのブロックに1行加えます。
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 9fd4d4a..0d793e4 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -12,6 +12,8 @@ Spork.prefork do
config.mock_with :rspec
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
+
+ ActiveSupport::Dependencies.clear
end
end
そしてconfig/application.rbも下のように修正します:
diff --git a/config/application.rb b/config/application.rb
index 590b85c..02b3ca4 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -38,5 +38,13 @@ module MyApp
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
+
+ ### Part of a Spork hack. See http://bit.ly/arY19y
+ if Rails.env.test?
+ initializer :after => :initialize_dependency_mechanism do
+ # Work around initializer in railties/lib/rails/application/bootstrap.rb
+ ActiveSupport::Dependencies.mechanism = :load
+ end
+ end
end
end
これでapp以下を修正した場合でもリロードしてテストしてくれます。
app以外、例えばconfig/application.rbやconfig/initializersの中は、rspecの起動を速くするためにプリロードしているので、sporkの再起動で解決します。これを自動的にやってくれるのがguard-sporkです。まずguard-sporkとFSEvent APIのRubyバインディングであるrb-fseventをインストールします。ただしここで使うguard-sporkは、後述するruby-debugのために私が改造したものです。
gem 'guard-spork', :git => 'https://github.com/irohiroki/guard-spork.git'
gem 'rb-fsevent'
加えたらbundleしてguard-sporkの初期化をします。
bundle
bundle exec guard init spork
そしてguardを起動。
bundle exec guard start
sporkはguardが起動してくれます。config/application.rbなどを更新するとguardがsporkを再起動します。
ところでguardが監視してくれるファイルの中にはconfig/routes.rbがないのですが、これは下の修正をすることでテストに反映できるようになります。
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 6f6a223..cffc9f5 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -19,4 +19,5 @@ Spork.prefork do
end
Spork.each_run do
+ MyApp::Application.reload_routes!
end
ruby-debugを使う
この時点では、rdebugを起動してコードの中にdebuggerと書いても止まってくれません。なぜなら、実際のテストはDRbサーバであるsporkで動いているからです(たぶん)。
この問題に対して、sporkの作者のTim Harper氏がrdebugのセッションをフォワードするプロキシを書いてくれました。これを使うと、debuggerが現れたときにsporkのターミナルにrdebugのプロンプトが出ます(autotestのターミナルではない)。ただし、一箇所RuntimeErrorが出るところがあるので、ここでは私の修正版を使います。まずcurlなどでプロキシモジュールをspecディレクトリに入れます。
curl https://gist.github.com/raw/814375/ccbe163559376e109e30574b1086a32fb626e374/spork-ruby-debug.rb > spec/spork-ruby-debug.rb
そしてそれをspec/spec_helper.rbからrequireします。
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 0d793e4..6f6a223 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,5 +1,6 @@
require 'rubygems'
require 'spork'
+require File.expand_path("../spork-ruby-debug", __FILE__)
Spork.prefork do
ENV["RAILS_ENV"] ||= 'test'
もちろんruby-debugもインストールしておきましょう。Gemfileに下の行を加えてbundleします。
gem 'ruby-debug19'
bundle
これで完成です。bundle execを付けるのを忘れずにguardを起動してください。
bundle exec guard start
実はオリジナルのguard-sporkだとsporkのプロセスがbackgroundへ回されてしまってrdebugのプロンプトが取れないのですが、そこは私の修正版で回避してあります。
以上の手順で作った環境をgithubに置きましたのでよろしければ参考にしてください。
Posted in Tech | Tags rails, testing | no trackbacks
Posted by irohiroki
Sat, 18 Dec 2010 15:09:00 GMT
(このエントリは、第58回 Rails勉強会@東京で発表した内容をまとめたものです。)
OmniAuthは、TwitterやGoogleなど様々な認証サービスプロバイダを統一したインターフェースで使えるようにしてくれるgemです。非常に便利なのでさっそく使おうとしたのですが、テストの書き方がわからなくて躓いたので、調べてわかったことやサンプルコードを公開します。
なお、OmniAuthは単体でも使えるのですが、伝統的なユーザ名とパスワードによる認証もサポートすることを想定して、Deviseと併用する構成となっています。
ポイントは以下の通りです:
- TwitterはOAuth 1.0
- 認証の過程でTwitterに3回のHTTPリクエストが飛ぶ
- それらをスタブで受ける
発表で使った資料を下に貼っておきます。最低限のことしか書かれていませんが、参考になれば。
Posted in Tech | Tags authentication, oauth, testing, twitter | no trackbacks
Posted by irohiroki
Thu, 09 Sep 2010 07:50:00 GMT
RubyKaigi2010のA Metaprogramming Spell BookのスピーカーであるPaolo Perrotta氏が著し、@kdmsnr氏が訳した『 メタプログラミングRuby』を読みました。
大変面白かったのでご紹介します。
目次は以下の通り。第1部だけ少し細かく書いてあります。
第1部 メタプログラミングRuby
- 第1章 月曜日:オブジェクトモデル
- 1.1 ビルと一緒の月曜日
- 1.2 オープンクラス
- 1.3 クラスの真実
- 1.4 クイズ:引かれていない線
- 1.5 メソッドを呼び出すときに何が起きているの?
- 1.6 クイズ:絡み合ったモジュール
- 1.7 オブジェクトモデルのまとめ
- 第2章 火曜日:メソッド
- 2.1 重複問題
- 2.2 動的メソッド
- 2.3 method_missing()
- 2.4 クイズ:バグ退治
- 2.5 もっとmethod_missing()
- 第3章 水曜日:ブロック
- 3.1 水曜日の過ごし方
- 3.2 クイズ:Ruby#
- 3.3 クロージャ
- 3.4 instance_eval()
- 3.5 呼び出し可能オブジェクト
- 3.6 ドメイン特化言語を書く
- 3.7 クイズ:より良いDSL
- 第4章 木曜日:クラス定義
- 4.1 クラス定義のわかりやすい説明
- 4.2 クイズ:クラスのタブー
- 4.3 特異メソッド
- 4.4 特異クラス
- 4.5 クイズ:モジュールの不具合
- 4.6 エイリアス
- 4.7 クイズ:壊れた計算
- 第5章 金曜日:コードを記述するコード
- 5.1 道案内
- 5.2 Kernel#eval
- 5.3 クイズ:属性のチェック(手順1)
- 5.4 クイズ:属性のチェック(手順2)
- 5.5 クイズ:属性のチェック(手順3)
- 5.6 クイズ:属性のチェック(手順4)
- 5.7 フックメソッド
- 5.8 クイズ:属性のチェック(手順5)
- 第6章 エピローグ
第2部 Railsにおけるメタプログラミング
- 第7章 ActiveRecordの設計
- 第8章 ActiveRecordの中身
- 第9章 安全なメタプログラミング
第3部 付録
- 付録A よく使うイディオム
- 付録B ドメイン特化言語
- 付録C 魔術書
- 付録D 参考書
- 付録E から騒ぎ
本のタイトルは『メタプログラミングRuby』ですが、メタプログラミングに限らずRubyでスムーズにプログラミングするために必要な知識がどっさり載っています。例えば、複数のクラスに同じクラスメソッドを定義するにはどういう方法があるか?クラスインスタンス変数とは何か?クラス変数との違いは?など、曖昧に覚えていることや使うたびに調べているようなことが、整理されて論理的に理解できるようになりました。
Rubyのコードを論理的に読み解くには、オブジェクトモデルとスコープの理解が欠かせません。Rubyのオブジェクトモデルには"メタクラス"あるいは"特異クラス"と呼ばれる隠れたクラスが潜んでおり、重要な役割を果たしています。
例えばあるクラスAのインスタンスaを作り、その特異クラスにメソッドを定義すると特異メソッドになります。
class A
end
a = A.new
class << a
def foo
p 'foo'
end
end
a.foo # => "foo"
しかしaのクラスであるAにはfooメソッドがありませんし、Aのスーパークラスにも特異クラスは現れません。
a.class # => A
A.instance_methods.grep(/foo/) # => []
A.ancestors # => [A, Object, Kernel, BasicObject]
では特異クラスはどこにあるのでしょうか?
次にスコープの例です。トップレベルでクラス変数@@aに値を入れたあと、適当なクラスAでも同様に@@aを使ったら、トップレベルの@@aは影響を受けるでしょうか?
@@a = 1
class A
@@a = 2
end
p @@a
答えは"受ける"です。上のコードの結果は2になります。では、インスタンス変数@aや、ローカル変数aだったらどうでしょうか?またそれはなぜでしょうか?
以上のような質問に答えるために、それぞれの場合の答えを丸暗記する必要はありません。単純なスコープのルールを覚えておけば済みます。スコープを理解すると、class_evalやinstance_evalの使いどころや、クロージャの意味まで明確になります。『メタプログラミングRuby』にはそれらを理解するための例や解説が豊富に載っています。物語形式になっていて、リラックスして読み進めることができると思います。
『メタプログラミングRuby』を読んだ一番の成果は、上述のオブジェクトモデルとスコープの理解が深まったことでした。これだけでプログラミングが楽になったと実感したほどです。そのほかの良かった点は、第5章の連続クイズが段階的な理解度テストになっていて手頃な腕試しができることや、Proc.new, proc, lambdaの違いなど、オフトピックも面白かったことです。以上、購入を考えている方の参考になれば幸いです。
Posted in Books | Tags book, Ruby | no trackbacks