BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース Ruby on Rails 2.0が公式リリース

Ruby on Rails 2.0が公式リリース

David Heinemeier Hansson(DHH)氏は先日、Ruby on Railsブログ内で、ほぼ1年の制作期間を経てRuby on Rails 2.0をリリース(source)したことを発表した。

今回のリリースでは新機能が目白押しで、多くの修正が加わり、洗練度も大幅に向上している。本リリースについてDavid氏は以下のように語っている。

Ruby on Rails同様、なんとも画期的な出来事である。私は個人的にこのフレームワークの取り組みに約4年半の歳月を費やしてきた。そしてほぼ同じくらいの時間を共にした貢献者もいた。その期間、自分達がどこまでやってきたのかを見てみると実に満足の行くものだった。当初の誇大広告を証明する為、それにこだわってさらに高いレベルを求め続けることができたのですから。

本リリースの「新機能紹介」リストは長い。Rails開発者の興味を最も引くと思われる主な機能は、以下のとおりである。

  • Action Pack: Resources(リソース)

2.0における大部分のアクションを解消した箇所です。RESTfulなライフスタイルに対する多数の改良を実現しました。まず、カスタムメソッド用のセミコロンを削除し、通常のスラッシュを採用しました。つまり、「/people/1;edit」は「/people/1/edit」となります。また、ルーティングリソースに名前空間機能を追加し、adminインターフェースなどが非常に制限しやすくなりました。:

map.namespace(:admin) do |admin|
admin.resources :products,
:collection => { :inventory => :get },
:member => { :duplicate => :post },
:has_many => [ :tags, :images, :variants ]
end

これで、inventory_admin_products_urlやadmin_product_tags_urlなどの名前付きルートが使用できます。この名前付きルートの拡散を追跡するため、routes.rbで作成されたすべての名前付きルートを一覧表示する「rake routes」タスクを追加しました。

また、リソースベースのすべてのコントローラをデフォルトで複数とする新しい規約を推進しました。これによって、単独のリソースが複数のコンテキスト内でマッピング可能でありながらも同じコントローラを参照することができます。以下に例を示します。


# /avatars/45 => AvatarsController#show
map.resources :avatars

# /people/5/avatar => AvatarsController#show
map.resources :people, :has_one => :avatar
  • Action Pack: Multiview(マルチビュー)

リソースの改善と平行して、マルチビューも改善しました。すでに#respond_toが用意されていますが、これをさらに発展させ、テンプレートに埋め込み、テンプレートのフォーマットはそのレンダリングエンジンから切り離しました。こうしてshow.rhtmlはshow.html.erbとなり、これはrespond_to内でformat.htmlを宣言したshowアクション用にデフォルトでレンダリングされるテンプレートです。これでshow.csv.erbに似た機能が利用可能となり、これはtext/csvを対象としますが、デフォルトのERBレンダラも使用します。

この結果、テンプレート用の新しいフォーマットはaction.format.rendererとなります。以下にいくつか例を示します。

  • すべてのフォーマット向けの同じshowテンプレート。
  • index.atom.builder: 以前はrxmlとして知られたBuilderフォーマットを使用して、application/atom+xmlというMIMEタイプに対してindexアクションをレンダリングします。
  • edit.iphone.haml: カスタムのHAMLテンプレートエンジン(デフォルトでは含まれない)を使用して、カスタムのMime::IPHONEフォーマットに対してeditアクションをレンダリングします。

iPhoneについて言えば、内部ルーティングにのみ使用される「偽の」タイプの宣言を簡素化しました。iPhone専用の特別なHTMLインターフェースを利用したいときなどに有効です。

  • Action Pack: Record identification(レコード識別)

URLを扱うコントローラおよびViewメソッドを簡素化して、リソース用の新しいドライバに掲載しました。また、モデルクラスをすぐにリソースルートに変換するための規約をいくつか追加しました。以下に例を示します。

  # person is a Person object, which by convention will 
# be mapped to person_url for lookup
redirect_to(person)
link_to(person.name, person)
form_for(person)
  • Action Pack: HTTP Loving

HTTP Loving(HTTPとの親和)お気づきかもしれませんが、Rails 2.0におけるAction Packは、HTTPおよびそのあらゆる栄光に近づくことがすべてです。リソース、多重表現などが思い浮かびますが、それだけではありません。今回HTTP基本認証と連動する新しいモジュールを追加しましたが、これはSSLでAPI認証を行うための優れた方法であることが分かっています。使用方法は極めて単純で、以下に一例を示します(ActionController::HttpAuthenticationではさらに多くの例が見られます)。

  class PostsController < ApplicationController
USER_NAME, PASSWORD = "dhh", "secret"

before_filter :authenticate, :except => [ :index ]

def index
render :text => "Everyone can see me!"
end

def edit
render :text => "I'm only accessible if you know the password"
end

private
def authenticate
authenticate_or_request_with_http_basic do |user_name, password|
user_name == USER_NAME && password == PASSWORD
end
end
end

また、膨大な数のファイルをリクエストするHTTPのオーバーヘッドに悩まされることなく、論理ユニット内でJavaScriptやスタイルシートファイルがはるかに簡単に構築できるようになりました。javascript_include_tag(:all, :cache => true)を使用すると、稼動中はpublic/javascripts/.jsを単独のpublic/javascripts/all.jsファイルに変換しながらも開発中はファイルを別々に保つため、キャッシュをクリアせずに繰り返し作業を行うことができます。

同じ方針に沿って、自身でリクエストを送信する気になれないブラウザをだますオプションを追加しました。ActionController::Base.asset_host = “assets%d.example.com”と設定すると、自動的にasset呼び出し(image_tagなど)がasset1~asset4に割り当てられます。これによって、ブラウザは、一度にさらに多くの接続を開始することができ、アプリケーションの知覚速度が向上します。

  • Action Pack: Security(セキュリティ)

追加設定なしでセキュアなアプリケーションの作成をさらに簡素化することは常に喜びであり、私達もRails 2.0に関して、これを多方面で行っています。最も重要なことは、CRSF攻撃に対処すべく内蔵メカニズムを搭載したということです。すべてのformおよびAjaxリクエストに特殊なトークンを含めることによって、アプリケーション外からリクエストが作成されないよう監視できます。新しいRails 2.0アプリケーションではこれはすべてデフォルトで有効であり、ActionController::Base.protect_from_forgeryを使用すると既存のアプリケーション内でも非常に簡単に有効にできます(詳細については、ActionController::RequestForgeryProtectionを参照してください)。

また、ユーザーによるページ内でのHTMLの組み込みを可能にしつつ、XSS攻撃への対処を簡素化しました。以前のTextHelper#sanitize手法は、ブラックリスト方式(セキュリティの維持が非常に困難)からホワイトリスト方式に変わりました。すでにサニタイズを使用しているなら、自動的により良い保護が保証されます。サニタイズを用いてデフォルトで使用可能なタグを微調整することもできます。詳細については、TextHelper#sanitizeを参照してください。

最後に、HTTP-only Cookie(source)のサポートを追加しました。これはまだすべてのブラウザによってサポートされているわけではありませんが、搭載されていれば使用可能です。

  • Action Pack: Exception handling(例外処理)

一般的な例外の多くは、アクションごとではなく共有レベルで救済した方が効果的です。これはrescue_action_in_publicを上書きすることで常に可能でしたが、その際にcaseステートメントを展開し、superを呼び出す必要がありました。そこで今回、あるアクションに対して一定の例外を宣言的に指し示すことができる、rescue_fromと呼ばれるクラスレベルのマクロを用意しました。以下に例を示します。


class PostsController < ApplicationController
rescue_from User::NotAuthorized, :with => :deny_access

protected
def deny_access
...
end
end
  • Action Pack: Cookie store sessions(Cookie保存セッション)

Rails 2.0におけるデフォルトのセッション保存は、クッキーベースとなりました。これは、セッションがファイルシステムやデータベースには保存されず、偽造が不可能なハッシュ形式でクライアントによって保存されるようになったことを意味します。これによって、従来のセッション保存に比べて大幅な高速化が実現するだけでなく、メンテナンスが不要になります。もはやcronジョブでセッションをクリアする必要もなく、削除し忘れたままtmp/session内に50万ファイルがたまってサーバーがクラッシュする、ということも起こりません。

  • Action Pack: New request profiler(新しいリクエストプロファイラ)

実使用に関わるボトルネックの箇所を突き止めるのは困難となる場合もありますが、利用スクリプト全体を追跡して、結果を総括的に報告できる新しいリクエストプロファイラを使えば、非常に簡単に実現できます。この使用例を以下に示します。

  $ cat login_session.rb
get_with_redirect '/'
say "GET / => #{path}"
post_with_redirect '/sessions', :username => 'john', :password => 'doe'
say "POST /sessions => #{path}"
$ ./script/performance/request -n 10 login_session.rb

HTMLおよびテキスト内でどこに時間を費やしたかについて完全な内訳が得られ、アプリケーションの高速化をどこで実現するかについて良いアイデアが生まれると思います。

  • Action Pack: Miscellaneous(その他)

注目すべきまた別の機能がAtomFeedHelperで、これを使用すると、強化されたBuilder構文を使用してAtom Feedがより簡単に作成できます。

  • Active Record: Performance(パフォーマンス)

Active Recordは膨大な数の修正と若干の微調整を経ましたが、大きな新機能が追加されたとは言えません。今回新たに加わったものは非常にシンプルなQuery Cacheですが、同様のSQLコールを同じリクエスト内から認識し、キャッシュした結果を返すというものです。これは、:includeやその他のメカニズムでの処理が難しいと思われるN+1状態にとっては特に便利です。また、フィクスチャのパフォーマンスが飛躍的に向上し、通常のフィクスチャ使用に基づく大部分のテストスイートよりも50~100%高速化しました。

  • Active Record: Sexy migrations(マイグレーション記述の洗練化)

マイグレーションの宣言に関して、効率が若干上がる新しい別のフォーマットを用意しました。(以前の記述例)

create_table :people do |t|
t.column, "account_id", :integer
t.column, "first_name", :string, :null => false
t.column, "last_name", :string, :null => false
t.column, "description", :text
t.column, "created_at", :datetime
t.column, "updated_at", :datetime
end

(新しい記述例)

create_table :people do |t|
t.integer :account_id
t.string :first_name, :last_name, :null => false
t.text :description
t.timestamps
end
  • Active Record: Foxy fixtures(フィクスチャ記述の向上)

フィクスチャを主キーのIDによって関連付けなければならないのではおもしろくありません。これに対処し、フィクスチャは以下のように記述できるようになりました。

  # sellers.yml
shopify:
name: Shopify

# products.yml
pimp_cup:
seller: shopify
name: Pimp cup

見て分かるとおり、もはやフィクスチャのIDを宣言する必要はなく、seller_idを使用して関係を参照する代わりに、sellerとフィクスチャ名を見るだけでいいのです。

  • Active Record: XML in, JSON out(XMLからJSONへ)

Active Recordはしばらくの間、XMLへのシリアライゼーションをサポートしてきました。2.0ではデシリアライゼーションも追加され、「Person.new.from_xml(“David“)」と記述して期待どおりの結果を得ることができるようになりました。また、XMLシリアライゼーションと同じ構文(nested associationsを含む)をサポートしたJSONへのシリアライゼーションも追加しました。「person.to_json」と記述するだけで、準備は完了です。

  • Active Record: Shedding some weight(スリム化)

Active Recordを少しスリム化して強靭にするため、acts_as_XYZ機能を削除し、これらをRails SVNリポジトリ上の個別のプラグインに入れました。したがって、acts_as_listを使用しているとすると、「do ./script/plugin install acts_as_list」と記述するだけで、何も起こらなかったように見えてすべてが移動します。

また、もう少し抜本的に、すべての商用データベースアダプタをgemに詰め込みました。したがって現在、RailsはMySQL、SQLite、およびPostgreSQL用のアダプタのみが搭載されています。これらはテストを行うための簡単かつ自発的なアクセスを備えたデータベースです。しかし、これは商用データベースが冷遇されていることを意味するわけではありません、むしろ、これらには主要なRailsディストリビューションから独立した自由なリリーススケジュールが設定できるのです。そして、商用データベースは、効率の良い動作のためには定期的にもっと多くの例外や試練を必要とする傾向があるので、おそらくこれは好都合です。

商用データベースアダプタはgem内に存在することとなり、すべてはactiverecord-XYZ-adapterという同じ名前付け規約に従います。したがって、gemを使用してactiverecord-oracle-adapterをインストールした場合、そのマシン上のすべてのRailsアプリケーションにおいてOracleが即座にアダプタの選択肢として利用可能になります。その利用にあたって、アプリケーション内で1行たりとも変更する必要はありません。

これは、新しいデータベースアダプタが、Railsの世界で好転しやすくなることも意味します。発表済みの規約に従ってアダプタをパッケージングする限り、ユーザーはgemをインストールするだけですべての準備が整います。

  • Active Record: with_scope with a dash of syntactic vinegar(with_scopeに若干の抑止効果をプラス)

コントローラ内(時にフィルタ内)で誤って使用されることを阻止するため、ActiveRecord::Base.with_scopeはprotectedとなり、代わってモデル自身の中でのみ使用することが推奨されます。それこそが設計目的であり、論理的に適合している部分です。しかし当然、これはあくまで推奨する、しないの話です。良い点と悪い点を比較評価した結果、モデル外でwith_scopeを使用したいと思った場合は、いつでも.send(:with_scope)を使用して呼び出すことができます。

  • ActionWebServiceを外し、ActiveResourceを採用

RailsがSOAP対RESTの議論においてどちら側につくかは、おそらく歴然でしょう。統合プロセスにおいて絶対にSOAPを使用する必要がある場合を除いて、SOAPの使用は断固としておすすめできません。その自然な流れとして、デフォルトのバンドルからActionWebServiceを削除しました。これはgem使用のインストールであるactionwebserviceを外しただけで、重要なメッセージは今までどおり送信します。

同時に、新しいActiveResourceフレームワークをベータ版から取り出し、デフォルトのバンドルに入れました。ActiveResourceはリソース用のActiveRecordのようなものです。これは同様のAPIを引き継ぎ、リソースドリブンの手法を用いてRailsアプリケーションとだけ連動するように設定されています。たとえば、標準的なscaffoldはActiveResourceによってアクセス可能です。

  • Rails: デバッガの復活

すべてをまとめると、概してRailsへの改良点は数え切れません。中でも私にとって好ましいのは、ブレークポイントがデバッガの形で復活したことです。これは単なるIRBダンプではなく、実際のデバッガでもあります。前後に進んだり、現在の位置をリストにしたりとさまざまなことが可能です。これはすべてruby-debug gemの優れた特徴がもたらすものであるため、新しいデバッガを機能させるにはruby-debug gemをインストールする必要があります。

このデバッガを使用するには、gemをインストールし、アプリケーション内のどこかに「debugger」を入れ、—debuggerまたは-uを用いてサーバーを起動するだけです。コードがデバッガコマンドを実行すると、デバッガはサーバーを動かしている端末内で直接利用可能となります。script/breakpointerなどは必要ありません。デバッガはテストでも使用できます。

  • Rails: 環境のクリーンアップ

Rails 2.0以前は、どこにでも置かれるconfig/environment.rbファイルは、各種1回限りの詳細設定に悩まされていたと思われます。今後は、これらの構成要素を自己完結ファイルに集めてconfig/initializersの下に置くことができ、これらは自動的にロードされます。新しいRails 2.0アプリケーションは、inflections.rb(独自の複数化ルール用)およびmime_types.rb(独自のMIMEタイプ用)という2つの形の例を搭載します。これによって、config/environment.rbにはデフォルト値だけを保存すればいいことが保証されます。

  • Rails: プラグインの順序付けを簡素化

Railsから相当量の機能を外してプラグインに入れたので、他のプラグインがこの機能性に依存することが考えられます。たとえばacts_as_listをacts_as_extra_cool_listプラグインの前にロードする必要性が生じる可能性があります(後者が前者を拡張するため)。

以前なら、これにはconfig.plugins内ですべてのプラグインに名前を付ける必要がありました。「とにかくacts_as_listを一番先にロードしたいだけなのに」という場合に非常に煩わしい問題でした。これからは、「config.plugins = [ :acts_as_list, :all ]」と記述することでまさにその希望が叶います。

David氏は、実際は他にも何百もの改良点があることを指摘している。

アップグレーディング

すでにRailsアプリケーションを使用しており、Rails 2.0にアップグレードしたいなら、まずRails 1.2.6に移行するよう推奨されている。この理由は、1.2.6にはdeprecation警告が含まれ、アプリケーションが1.2.6で警告なく動作するなら、Rails 2.0でもうまく動作するとされているからである。 

Ruby on Railsのさらなる詳細については、Ruby on RailsのWebサイト(英語)を参照のこと。


原文はこちらです:http://www.infoq.com/news/2007/12/rails20-released


この記事に星をつける

おすすめ度
スタイル

BT