2012-02-10
Rails3 レシピブック
まだ Rails2 が主流だったころ Rails を勉強していたんですが、Google App Engine が出たので、途中でやめて Python に移ってしまいました。それから去年までずっと Python。
今年から Ruby に戻って、Rails3 に再挑戦しています。Python で Django や Kay といったフレームワーク使っていたから、Rails2 のときどこで躓いていたのかわからないくらい、Rails3 にすんなり入れました。他のフレームワークで培ったノウハウは Rails でも生かせる、というのを実感中。
足りないのは「Rails3 ではメールどうやればいいんだっけ」「Rails3 ではリレーションどうすればいいんだっけ」といった、Rails3 でのやり方くらいです。そこで本書のようなレシピブックの出番。
Google 先生に聞くのもいいですけど、やっぱり手元にあった方が調べるのに早いです。本書は Rails 入門レベルのレシピからだんだん高度になっていくので、Rails 入門したてでもなんとか読み進めていける内容だと思います。
Rails 初挑戦でいきなり本書だけ、っていうのはさすがにキツイと思いますが、既に他の言語でフレームワークに慣れ親しんでいる人なら、Rails の勉強はレシピブックとネットの情報で足りるんじゃないでしょうか。私の場合は、今のところ何とかなっています。
ソフトバンククリエイティブ
売り上げランキング: 60469
2012-02-08
Ruby でベンチマーク計測
Java のサーブレットコンテナ、まぁ Jetty なんですけど、Jetty の HTTP サーバーとしての性能がどれくらいか分かる資料が無かったので、Ruby でベンチマークを計測するスクリプトを書いてみました。ついでにサーブレットも計測しています。benchmark モジュール初挑戦。
# coding: utf-8 require "open-uri" require "benchmark" HTML_URL = "http://192.168.56.101:8080/helloworld/" SERVLET_URL = HTML_URL + "hello" # ベンチマーク対象のメソッド def open_service(uri) # 指定した URI にアクセスしてレスポンスを取得するだけ open uri do |s| s.read end end # 渡したブロックを 1, 10, 100, 1000 回繰り返すのにかかる時間を計測 def do_benchmark(caption, &block) Benchmark.benchmark(caption + Benchmark::CAPTION, 7, Benchmark::FMTSTR) do |r| [1, 10, 100, 1000].each do |n| # block を n 回繰り返したときのベンチマーク r.report n.to_s do n.times &block end end end end # 静的ファイルにアクセス do_benchmark("static ") do open_service(HTML_URL) end puts # サーブレットにアクセス do_benchmark("servlet") do open_service(SERVLET_URL) end
このスクリプトを実行した結果は次の通り。
C:\work>ruby benchmark_jetty.rb static user system total real 1 0.078000 0.312000 0.390000 ( 0.419042) 10 0.016000 0.000000 0.016000 ( 0.128013) 100 0.156000 0.078000 0.234000 ( 1.221122) 1000 0.764000 1.560000 2.324000 ( 12.743274) servlet user system total real 1 0.000000 0.000000 0.000000 ( 0.014002) 10 0.000000 0.016000 0.016000 ( 0.134013) 100 0.063000 0.156000 0.219000 ( 1.281129) 1000 1.451000 0.670000 2.121000 ( 13.073307)
このスクリプトで計測したデータが、実際に役に立つかどうかは微妙ですけどね。ていうか、たぶん JMeter あたりを使って計測し直すこと間違いなし。
2012-02-06
Sequel でマイグレーション
Sequel にはマイグレーション機能があるので、Rails と同じようにテーブルの作成やスキーマ変更ができます。
サンプル程度ならアプリケーションのファイルに create_table べた書きでいいけど、ちゃんとしたサービス作るときはマイグレーションを使ったほうが良いですよね。
マイグレーションファイルの名前は、最初に通し番号またはタイムスタンプを付けて、APP_ROOT/db/migrate ディレクトリに配置するのが慣習。
001_create_users.rb
Sequel.migration do up do create_table :users do primary_key :id String :name, :null => false String :password, :null => false DateTime :created_at end end down do drop_table :users end end
あとは APP_ROOT で次のコマンドを実行。
sequel -m ./db/migrate sqlite://sample.db
たったこれだけ。簡単ですね。sqlite://〜 の部分は、使っているデータベースに合わせて修正してください。
2012-02-03
Sinatra + OmniAuth で Twitter の OAuth を試してみた
Sinatra アプリの認証に Warden を使おうとしてたけど、「ユーザー名とパスワードを自前で保存したくない」と思い直して、OAuth や OpenID を検討し始めました。Twitter や Facebook や GitHub など、いろんな OAuth に対応したいから、使うライブラリは OmniAuth かな。
Sinatra + OmniAuth で、Twitter の OAuth を使って認証するサンプルを書いてみました。
# coding: utf-8 require "sinatra" require "omniauth" require "omniauth-twitter" # Twitter の OAuth を使うなら必須 # Sinatra のセッションを有効にする enable :sessions # OmniAuth の設定 use OmniAuth::Builder do # Twitter の OAuth を使う provider :twitter, "Consumer key", "Consumer secret" end get "/" do erb :index end # Twitter の認証が成功したら呼び出される get "/auth/:provider/callback" do # 認証情報は request.env に格納されている @auth = request.env["omniauth.auth"] erb :home end __END__ @@layout <!DOCTYPE html> <html> <head> <title>Sinatra-OmniAuth</title> </head> <body> <%= yield %> </body> </html> @@index <a href="/auth/twitter">Twitter でログイン</a> @@home <h1>Wellcome</h1> <pre> <%= @auth %> </pre>
たったこれだけのコードで実装できてしまった…。以前、Python + AppEngine + Kay Framework で Twitter の OAuth に挑戦したときは、結構コード書いたのにな。
2012-02-02
Sequel::Model でキャストできない値をセットしたら例外が発生するのを抑制してみる
例えば、Sequel::Model を使って次のようなクラスを定義したとします。
# coding: utf-8 require "sequel" DB = Sequel.sqlite("test.db") DB.create_table? :records do primary_key :id Date :date String :summary Float :kcal DateTime :created_at end class Record < Sequel::Model plugin :validation_helpers def validate validates_presence [:summary, :kcal, :date] validates_numeric :kcal validates_type Date, :date validates_type String, :summary validates_type DateTime, :created_at end end
このクラスに対して
Record.new(:kcal => "hoge")
とか
@record = Record[id] @record.set(:kcal => "hoge")
とかやると、Float に変換できないため例外が発生してしまいます。
入力はとりあえず何でも受け付けて、検証してみてエラーだったらメッセージを表示したいので、セットしたときに例外を出されたら都合が悪い。
そこで、キャストできなかったとき例外が発生するのを抑制してみます。
Sequel::Model.raise_on_typecast_failure = false
これで OK。ActiveRecord と同じ感覚で使っていたから、ハマってしまいました。


