Rails中的RESTful DCI上下文



我第一次了解数据、上下文和交互(DCI)是通过这篇博客文章。被这个概念所吸引,我努力将它构建到我的下一个Rails应用程序中。由于DCI与MVC协同工作,我认为同时使API RESTful不会太难。因此,我制作了一个RESTful资源Report,并将其扩展到各种上下文中。我在Rails中实现上下文的方式是为扩展控制器操作的模块创建一个目录/app/contexts/。所以我的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

注意,除了控制器上下文之外,我还用Role扩展了current_user

以下是它的工作原理:

  1. 用户登录
  2. 用户的角色是RegisteredUser
  3. RegisteredUser的默认上下文是Search(如/app/roles/registered_user.rb中所定义)
  4. Search上下文中,用户只能查看已发布的报告
  5. 用户按下"创建新报告"按钮,上下文将更改为Submission并存储在current_user的会话中
  6. 然后,用户通过多步骤表单提交报告
  7. 每次用户通过遍历表单来保存报告时,/app/contexts/submission.rb上下文都会处理该操作

还有其他几个上下文(评论、编辑等)和角色(合著者、编辑等。)

到目前为止,这种方法在大多数情况下都很有效。但有一个缺陷:当用户打开多个浏览器窗口并更改其中一个窗口的上下文时,所有其他窗口都将处于错误的上下文中。如果用户处于多步骤表单的中间,然后在Search上下文中打开一个窗口,则这可能是一个问题。当他切换回表单并点击"下一步"时,控制器将执行由Search上下文而不是Submission上下文定义的操作。

我可以想出两种可能的方法:

  1. 使用上下文名称为Report资源命名空间。因此用户将访问诸如/search/reports/submission/reports/1之类的URL。这对我来说似乎不是RESTful,我宁愿尽可能保持URL的干净
  2. 将上下文名称放在隐藏字段中。这种方法要求开发人员记住将隐藏字段放在网站上的每个表单中,而且它不适用于GET请求

有没有其他方法可以解决这个问题,或者更好的整体实现?

我知道这个项目,但它对我们的需求来说太有限了。

如果您想允许多个上下文,那么显然您必须将确定当前上下文的信息放在一些选项卡之间不共享的存储中。在Rack/Rails中实现的会话使用cookie,并且cookie在选项卡之间共享。

只是把上下文放在一些不共享的东西上。context=viewer URL参数怎么样?

谈到REST,我认为在不同的上下文中资源是否相同是有争议的。有人可能会说,"访问"用户的报告与"管理"用户的报表不同。在这种情况下,RESTy方法可能会为请求命名名称空间(再次将上下文放入URL中),例如/vising/reports/1vs/administration/reports/1。

将上下文放入URL的第三种方法是将其用作域名的一部分。

相关内容

  • 没有找到相关文章

最新更新