私が最初にデータ、コンテキスト、インタラクション(DCI)について学んだのは、このブログ投稿でした。この概念に魅了された私は、次の Rails アプリケーションに組み込むことにしました。DCI は MVC と連携して動作するため、API を同時に RESTful にすることはそれほど難しくないと考えました。そこで、RESTful リソースを作成し、Report
さまざまなコンテキストで拡張しました。/app/contexts/
Rails でコンテキストを実装する方法は、コントローラー アクションを拡張するモジュール用のディレクトリ を作成することでした。だから私のようにreports_controller.rb
見える:
class ReportsController < ApplicationController
before_filter :only => :new do |c|
c.switch_context("submission")
end
# GET /reports
def index
@context.report_list
end
# GET /reports/1
def show
@context.display_report
end
# GET /reports/new
def new
@context.new_report
end
# GET /reports/1/edit
def edit
@context.edit_report
end
# POST /reports
def create
@context.create_report
end
def update
@context.update_report
end
# DELETE /reports/1
def destroy
@context.destroy_report
end
protected
def switch_context(context_name)
session[:context] = context_name
context = session[:context].camelize.constantize
@context ||= self.extend context
end
end
そしてapplication_controller.rb
、コンテキストを次のように設定しますbefore_filter
。
class ApplicationController < ActionController::Base
before_filter :contextualize
protect_from_forgery
protected
# Sets the context of both current_user and self
# by extending with /app/roles/role_name
# and /app/contexts/context_name respectively
def contextualize
# Extend self (ActionController::Base) with context
if session[:context]
context_class = session[:context].camelize.constantize
if current_user.allowed_contexts.include?(context_class)
context_class = current_user.context if context_class == Visiting
else
context_class = Visiting
end
else
context_class = current_user.context
end
@context ||= self.extend context_class
end
end
コントローラー コンテキストに加えて、拡張current_user
していることに注意してください。Role
仕組みは次のとおりです。
- ユーザーがログインします。
- ユーザーの役割は
RegisteredUser
です。 RegisteredUser
のデフォルトのコンテキストはSearch
(で定義されている/app/roles/registered_user.rb
) です。- コンテキスト内
Search
では、ユーザーは公開されたレポートのみを表示できます。 - ユーザーが「新しいレポートの作成」ボタンを押すと、コンテキストが変更され、のセッション
Submission
に保存されます。current_user
- 次に、ユーザーは複数ステップのフォームからレポートを送信します。
- ユーザーがフォームをステップ実行してレポートを保存するたびに、
/app/contexts/submission.rb
コンテキストがアクションを処理します。
その他のいくつかのコンテキスト (レビュー、編集など) と役割 (共著者、編集者など) があります。
これまでのところ、このアプローチはほとんどの場合うまく機能しています。しかし、欠点があります。ユーザーが複数のブラウザー ウィンドウを開き、そのうちの 1 つのコンテキストを変更すると、他のすべてのウィンドウが間違ったコンテキストになります。これは、ユーザーがマルチステップ フォームの途中でSearch
コンテキスト内のウィンドウを開く場合に問題になる可能性があります。彼がフォームに戻って「次へ」をクリックすると、コントローラーはSearch
コンテキストではなくコンテキストによって定義されたアクションを実行しSubmission
ます。
私が考えることができるこれを回避する2つの可能な方法があります:
Report
リソースをコンテキスト名で名前空間化します。したがって、ユーザーは/search/reports
やなどの URL にアクセスします/submission/reports/1
。これは私には RESTful ではないように思われるので、URL をできるだけきれいに保ちたいと思います。- コンテキスト名を非表示フィールドに入れます。この方法では、開発者は隠しフィールドをサイトのすべてのフォームに配置することを覚えておく必要があり、GET 要求では機能しません。
この問題を回避する他の方法、またはより良い全体的な実装はありますか?
このプロジェクトのことは知っていますが、私たちのニーズにはあまりにも限定的です。