※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

リクエストラムダについて詳しく

Update: 用語のちょっとしたこと:ブロックへのリクエストをマッピングするアイデアをよりよく反映させるために、この特徴を「リクエストラムダ」と呼んでいます。

毎日(または週末の数時間)Waves のさまざまな側面にほんの少し詳しく説明するために、ちょっとずつ試しては書いています。最初にされるもっとも共通する質問の1つは 「Waves はフレームワークXとどんな違いがあるのですか?」です。 何がWavesを特徴付るかフロントページにリンクしているけれど、あなたは今のところ簡単な案内を受けられるだけです。詳細については何か異なったことを通して本当に理解できるだけです。 (?)

(余談ですが、私は Ruby はこんな風だと思っています。 Ruby がどうしてこんなにすばらしいかをある種の懐疑論者に絶えず説明しています。 多くの特徴を記述する人がたくさんいますし、懐疑論者は「こっちの言語でも出来るよ」といいます。それは確かですが結局、特徴に関することではなく、どのように実行されるかということなのです。思うに、 C++ はイテレータとすばらしいコレクションライブラリを持っています。しかし、それらはまだ Enumerable ではないのです。)

私は、メーリングリストでのリクエストマッピングのコンセプトに関する議論に、Wavesのイロハを確認する最初の試みとしてちょっと興味を持ちました。リクエストマッピングは Rails や Merb の routes のようなものです。 しかしいくつか根本的な違いがあります。 リクエストマッピングは1ブロックのコードが1リクエストとして対応付けます。

ここでは、パスだけではなく全体のリクエストについて話しているのでリクエストマッピングと読んでいます。URL や パス, HTTP メソッドやアクセプとヘッダ等を受け入れてください。 パスだけでなく全体のリクエストにあわせてください。さらにあなたが行いたいようにどんなマッピングでもブロックに記述できます。例えば Waves では、 “hello world” アプリケーションはコントローラやビュー無しにたった1行のマッピングファイルです。

path('/') { 'Hello World!' }

または、こんな風にも出来ます。:

# add / update the given resource for the given model
path %r{^/#{model}/#{name}/?$}, :method => :post do |  model, name |
  use( model ) | controller { update( name ) }; redirect( url )
end


HTTP POST に合わせるために正規表現を使っています。パラメータとしてブロックにバインディングするために正規表現を通しています。メソッドか変数のモデルと名前で 別の場所で読み込み可能なルールを作るのを助けるためのマッピングモジュールを定義する必要があります。ブロックの中では、 URL に基づいて使用されるリソース(model)を設定し、適切なコントローラの update メソッドを呼びます。最後に、model と同じ URL にリダイレクトします。

Railsのようなフレームワークのルートと重要な違いは2つ:

  • mapping はリクエストと controller または view メソッドによって明確に作られています。 どんな controller メソッドもそれとなく提供されています。 URLにより不適切に呼び出されるコントローラメソッドを追加することを心配する必要はありません。 (または、もし呼び出されたら、 あなたが実行されるようにマッピングを作成したからです。)
  • コントローラには責任がそれほどありません、これはマッピングにたくさん責任があることを意味します。 Waves ではコントローラはビューを決定しませんが、他のフレームワークではコントローラに責任がたくさんあるかもしれません。(?)そしてコントローラが気にしない大部分はマッピング自身の責任になります。

コントローラとビューの完全な decouples は古典的な MVC からの出発です。事実、ほとんどのWebアプリケーションフレームワークはすでにこれらを部分的にどうにか decouples しています; Waves ではすでにこうなっています。

すべてのコントローラは、Waves ではモデルで要求を処理するよう想定されています。モデルはリクエストについて何も知りません。 モデルはリクエストパラメータか404ステータスかを知りませし、そうすべきではありません。 こうしてコントローラはモデルへの一種の受付役を務め、 リクエストコンテキストから隔離し続けます。リクエストマッピングは一種のメタコントローラになります。

同じ方法で、フィルタはコントローラではなくリクエストマッピング上で扱われます。これによりはるかに簡単にいろいろなコントローラに一貫してフィルタを適応できるようになります。例えば、誰でもまず管理画面に必ずログインさせたいと仮定してください。 このような要求フィルタを作成するかもしれません:

before %r{^/admin/} do | model, name |
  redirect('/login') unless session[:user]
end

今のところ、/admin/ で始まるどんなパスもログインを必要とするため、安全なコントローラメソッドを偶然 expose する方法はありません。(コントローラに新しいメソッドを追加するだけでできないのかというべきではありません。あなたはマッピングを台無しにしなければいけなくなります。) そして、どんな要求でも実際にどう処理されるかはすべて1箇所にあります。

もちろん。モジュールコンポーネントにマッピングするよう再構成できます(そうすべきです)。 Waves では Waves::Mapping::PrettyUrls モジュールでどのように処理するか例を提供します。 「きれいな URLs」を利用した一般的なマッピングパターンのパッケージです。( id の代わりに name でアクセスされたリソース)。あなたは使用に耐えるアプリケーションへの 強力なマッピングを含んでいるといえます。これはデフォルトアプリケーションがセットアップされる方法です。:

module Blog
  module Configurations
    module Mapping
      extend Waves::Mapping
      # your custom rules go here
      include Waves::Mapping::PrettyUrls::RestRules
      include Waves::Mapping::PrettyUrls::GetRules
    end
  end
end

あなたは共通のマッピングパターンを開発するので、これらを include することでモジュールに簡単にマッピングパターンを置けます。 Waves ではどんなパターンも押し付けません。( PrettyUrls に加え、たくさんの一般的なパターンを導入する予定ですが) そしてこれは Waves の哲学のすばらしい例でもあります。 Ruby は既に DSLs を定義して、モジュールで再利用可能なコードをパッケージする機能を提供しています。「Ruby で既に提供されているものを使うだけ」と理解している Waves使いだけが、URLs のセットを定義した特別なメソッドを必要としてるわけではありません。(?)

以上で、何が Waves はユニークで強力にしているか垣間見る役になったことと思います。 次の投稿で、ブロックによる MVC wiring の intracacies を始める予定です。それまでコメントしたり質問をすることを躊躇わないでください。