12

私が最初にデータ、コンテキスト、インタラクション(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

仕組みは次のとおりです。

  1. ユーザーがログインします。
  2. ユーザーの役割はRegisteredUserです。
  3. RegisteredUserのデフォルトのコンテキストはSearch(で定義されている/app/roles/registered_user.rb) です。
  4. コンテキスト内Searchでは、ユーザーは公開されたレポートのみを表示できます。
  5. ユーザーが「新しいレポートの作成」ボタンを押すと、コンテキストが変更され、のセッションSubmissionに保存されます。current_user
  6. 次に、ユーザーは複数ステップのフォームからレポートを送信します。
  7. ユーザーがフォームをステップ実行してレポートを保存するたびに、/app/contexts/submission.rbコンテキストがアクションを処理します。

その他のいくつかのコンテキスト (レビュー、編集など) と役割 (共著者、編集者など) があります。

これまでのところ、このアプローチはほとんどの場合うまく機能しています。しかし、欠点があります。ユーザーが複数のブラウザー ウィンドウを開き、そのうちの 1 つのコンテキストを変更すると、他のすべてのウィンドウが間違ったコンテキストになります。これは、ユーザーがマルチステップ フォームの途中でSearchコンテキスト内のウィンドウを開く場合に問題になる可能性があります。彼がフォームに戻って「次へ」をクリックすると、コントローラーはSearchコンテキストではなくコンテキストによって定義されたアクションを実行しSubmissionます。

私が考えることができるこれを回避する2つの可能な方法があります:

  1. Reportリソースをコンテキスト名で名前空間化します。したがって、ユーザーは/search/reportsやなどの URL にアクセスします/submission/reports/1。これは私には RESTful ではないように思われるので、URL をできるだけきれいに保ちたいと思います。
  2. コンテキスト名を非表示フィールドに入れます。この方法では、開発者は隠しフィールドをサイトのすべてのフォームに配置することを覚えておく必要があり、GET 要求では機能しません。

この問題を回避する他の方法、またはより良い全体的な実装はありますか?

このプロジェクトのことは知っていますが、私たちのニーズにはあまりにも限定的です。

4

1 に答える 1

3

複数のコンテキストを許可する場合は、明らかに、タブ間で共有されていないストレージに現在のコンテキストを決定する情報を配置する必要があります。ラック/レールに実装されているセッションはCookieを使用し、Cookieはタブ間で共有されます。

コンテキストを共有されていないものに入れるだけです。context = viewer URLパラメーターはどうですか?

RESTについて話すと、リソースが異なるコンテキストで同じであるかどうかは議論の余地があると思います。「訪問中」のユーザーのレポートは「管理中」のユーザーのレポートとは異なると主張する人もいるかもしれません。その場合、RESTyアプローチは、おそらくリクエストに名前空間を付けます(これにより、コンテキストがURLに入れられます)。たとえば、/ visiting / reports/1と/administering/ reports/1のようになります。

そして、コンテキストをURLに入れる3番目の方法は、それをドメイン名の一部として使用することです。

于 2012-02-18T14:11:49.790 に答える