クライアントとサーバーの両方で動くフレームワークでは、「どこで何か動いているか」を知ることが困難になりがちです。話をわかりやすくするために、アプリケーションをいくつかのパーツに分けた上で、それぞれに対して、どこで動いているかを説明します。
Voltでは、コントローラーとモデルとビューには、クライアント側とサーバー側の両方でアクセスすることができます。ただ、一般的には コントローラー と ビュー は通常クライアント側だけで動作します。将来的には、ロード時間の高速化のため、最初のページのリクエストではサーバー側でまず実行されるようになる予定です。
モデルはクライアントとサーバーの両方で動きます。モデルが変更された場合、そのバリデーション/パーミッションの処理、変更が許可されたものであるかをチェックするために、まずクライアントサイドで実行されます。それが成功したら、変更はサーバーに通知され、サーバー側でモデルが再度読み込まれ、サーバー側に変更が反映されます。サーバー側でもバリデーション/パーミッションの処理が実行され、それにパスすると、モデルは保存されて他のクライアントにも同期します。このことはモデルのコードはクライアントとサーバーのどちらでも動作する必要があるということを意味しています。
タスクは興味深い機能です。サーバー側のコードをクライアント側から呼び出すことを意図しています。Voltの同期モデルによって、書いたアプリケーションのほとんどはクライアント側で動作します。クライアント側でコードが動作することで、高速なリロードやアクション間でのデータの共有が実現できます。しかし、クライアント側からサーバー側のコードを呼び出したい場合は多いでしょう。
タスクはTaskインスタンスのすべてのメソッドに対して非同期のインターフェースを提供します。すべてのパブリックなタスクメソッドにアクセスするには…
Volt.server?
と Volt.client?
を利用すれば、コードがサーバーとクライアントのどちらで動作しているか確認することができます。しかし時には、クライアント側ではコードを一切コンパイルしないようにしたい場合もあるでしょう。そのような場合には、Opalが提供している、コードをコンパイルしないようにするための方法を利用します。以下のようにします。
if RUBY_PLATFORM != 'opal'
...
end
上記の冴えた方法によって、完全にコードは取り除かれ、クライアントに送信されることはありません。ただ、この方法はrequire
には効果がないことに注意してください。Opalはコンパイル時にrequireを実行するからです。
どうすればアプリケーションをセキュアに保つことができるか、ということには誰もが関心があると思います。セキュリティに関して考慮すべきは以下の2点です。: 1) モデルのパーミッション 2) タスク
モデルのパーミッションは、データがどのように変更されるかを決定し、データが変更/参照されたとき、クライアント側とサーバー側の両方で動作します。バックエンドのフレームワークとは異なり、API を用意することなく、クライアント側からデータの変更が行えます。モデルのパーミッション を追加するのは、ビジネスロジックにしたがってデータを保護するためのシンプルな方法です。詳細は パーミッション のページを参照してください。User モデルは、初期状態でパーミッションの設定がされています。
タスクは、バックエンドのフレームワークにおけコントローラーに似ています。ただ、HTTP を利用するのではなく、メソッドのレベルで動作することが異なります。タスクのすべての public メソッドは、クライアントからクラスレベルのメソッドを利用して呼び出すことができます。引数はバックエンドに渡され、クライアントへはそのメソッドの戻り値が返されます。タスクに渡されるメソッドの引数はバリデーションされなければなりません。なぜかというと、JSON (および Time オブジェクト) にシリアライズに可能なデータであれば何でも含むことができるからです。もしタスクの内部で使われる場合でも、モデルはパーミッションのバリデーションを実行します。
1)モデルのパーミションが設定され、それが、そのデータの参照や操作の際に求められる動作と合致するようにしてください。 2) 引数としてタスクに渡されるデータのバリデーションを行ってください。例えば、もしタスクからリモート API をリクエストする場合、URL 全体をクライアント側に渡さないようにしましょう。もしそうしてしまうと、いかなる URL にもヒットしてしまいます。もし全ての URL を渡す場合には、ヒットさせたい URL に合致するようなドメインのチェックなどを行うようにしてください。