君の瞳はまるでルビー - Ruby 関連まとめサイト

Sinatra のスコープについて

最終更新: 2015-03-31 (火) 21:53:20 (1325d)

目的

Sinatra の重要な概念の1つにスコープという考え方があります。

スコープの理解が本ページの目的です。

理解すべきスコープは以下の2種類です。

  • アプリケーション/クラス
  • リクエスト/インスタンス

処理の実行がどちらのスコープで行われるかによって利用できる機能が変わります

書いている処理がどちらのスコープに属しているのかを理解するのはとても重要です。

それぞれのスコープで使える機能を以下にまとめています。

それぞれのスコープについて

アプリケーション/クラススコープ

以下の場所で実行される処理は、

  • アプリケーションのクラス本体内(アプリケーションクラスを定義しなかった場合、実行プログラム直下内)
  • configure ブロック内
  • helpers ブロック内
  • `set` の値として使った Proc またはブロック内

アプリケーション/クラススコープの機能が使えます。

リクエスト/インスタンススコープ

以下の場所で実行される処理は、

  • get/head/post/put/delete ブロック内
  • before/after/error/not_found ブロック内
  • helper ブロック内で定義したメソッド内
  • テンプレート内

リクエスト/インスタンススコープの機能が使えます。

事例

アプリケーションの定義(app.rb)

# coding: UTF-8

require 'sinatra'

# アプリケーション/クラススコープ(実行プログラム直下内)

def custom_method1
  # アプリケーション/クラススコープ(実行プログラム直下内)
end

configure do
  # アプリケーション/クラススコープ(configure ブロック内)
end

helpers do
  # アプリケーション/クラススコープ(helpers ブロック内)

  def in_world
    # リクエスト/インスタンススコープ(helpers ブロック内で定義したメソッド内)
    @world = 'world'
  end
end

get '/' do
  # リクエスト/インスタンススコープ(get ブロック内)
  @hello = 'Hello'
  in_world
  erb :hello
end

テンプレートの定義(views/hello.erb)

<!-- リクエスト/インスタンススコープ(テンプレート内) -->
<%= @hello %> <%= @world %>

豆知識

これ以降は、ちょっとした豆知識です。タイトルを見て気になった方は、娯楽の1つとして読んで貰えればと思います。

この豆知識は公式のサイトに書かれている内容ではありません。

使ってみて、疑問点から Sinatra のソースコードの中身を見てみて、結果として出てきた想像した1つの解釈であることを事前にご了承ください。

スコープは「概念」と「実現手段」の2つの側面から命名されている

Sinatra のスコープの名前は長くややこしいものです。なぜこんなにも長いのか?命名の起源がわかるとスッキリします。

スコープは「概念」「実現手段」という2つの側面の両方がわかるように命名されています。

  • 「アプリケーション」と「リクエスト」は「概念」
  • 「クラス」と「インスタンス」は「実現手段」

これらには以下のような相関関係があります。

  • 「アプリケーション」スコープという「概念」は、「クラス」スコープという「手段によって実現」されている。
  • 「リクエスト」スコープという「概念」は、「インスタンス」スコープという「手段によって実現」されている。

これらの相関関係を反映した結果、以下のような呼び方をしています。

  • アプリケーション/クラススコープ
  • リクエスト/インスタンススコープ

なぜそうなるのか?

語弊を気にせずざっくりと言うと 「Sinatra はリクエスト毎にアプリケーション自身のインスタンスを生成し、そのインスタンスにリクエストを処理させているから」です。

クラススコープで定義したメソッドや変数は、インスタンスを横断して参照でき、1つのアプリケーション内で共有できます。これがアプリケーションスコープです。

リクエスト毎に生成されたアプリケーションインスタンスは、独自にインスタンス変数を持てます。これがリクエストスコープです。

アプリケーションのインスタンスがリクエスト毎に生成されているからこそ、ハンドラでインスタンス変数に値を設定し、テンプレートでその値を参照できます。

もしも1アプリケーション=1インスタンスであったなら、以下のいずれかの制約が課せられることになります。

  • リクエスト内の情報伝達に引数渡しを使わなければならない。
  • 同時に処理可能なリクエストを1つにしなければならない。

Sinatra は、リクエスト毎にアプリケーションのインスタンスを生成することで以上のいずれの制約を受けること無く、以下のメリットを与えてくれます。

  • インスタンス変数の利用によってリクエスト内の情報伝達が簡単にできる。
  • リクエストの並列処理ができる。

「概念」だけで理解するなら、アプリケーションスコープ・リクエストスコープという名前で十分でしょう。 しかし、名前から「実現手段」も想像できるようにもなっています。

コメント

コメントはありません。 コメント/sinatra/about/scope

お名前: