Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails中的RESTful DCI上下文_Ruby On Rails_Ruby_Rest_Dci - Fatal编程技术网

Ruby on rails Rails中的RESTful DCI上下文

Ruby on rails Rails中的RESTful DCI上下文,ruby-on-rails,ruby,rest,dci,Ruby On Rails,Ruby,Rest,Dci,我第一次了解DCI是通过。我被这个概念迷住了,努力将它构建到我的下一个Rails应用程序中。由于DCI与MVC协同工作,我认为同时使API保持RESTful并不难。所以我制作了一个RESTful资源,Report,并用各种上下文对其进行了扩展。我在Rails中实现上下文的方法是为扩展控制器操作的模块创建一个目录,/app/contexts/。因此,我的报告\u controller.rb如下所示: class ReportsController < ApplicationControlle

我第一次了解DCI是通过。我被这个概念迷住了,努力将它构建到我的下一个Rails应用程序中。由于DCI与MVC协同工作,我认为同时使API保持RESTful并不难。所以我制作了一个RESTful资源,
Report
,并用各种上下文对其进行了扩展。我在Rails中实现上下文的方法是为扩展控制器操作的模块创建一个目录,
/app/contexts/
。因此,我的
报告\u 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
请注意,除了控制器上下文之外,我还使用
角色扩展了
当前用户

下面是它的工作原理:

  • 用户登录
  • 用户的角色是
    RegisteredUser
  • RegisteredUser
    的默认上下文是
    Search
    (定义见
    /app/roles/registered_user.rb
  • 搜索
    上下文中,用户只能查看已发布的报告
  • 用户按下“创建新报告”按钮,上下文更改为
    提交
    ,并存储在
    当前用户的会话中
  • 然后,用户继续通过多步骤表单提交报告
  • 每次用户通过单步执行表单保存报告时,
    /app/context/submission.rb
    上下文将处理该操作
  • 其中包括几个其他上下文(评论、编辑等)和角色(合著者、编辑等)

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

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

  • 使用上下文名称命名
    报告
    资源。因此,用户将访问URL,如
    /search/reports
    /submission/reports/1
    。这对我来说似乎不是RESTful的,我宁愿保持URL尽可能干净
  • 将上下文名称放在隐藏字段中。这种方法要求开发人员记住将隐藏字段放在站点上的每一个表单中,并且它不适用于GET请求
  • 有没有其他方法可以解决这个问题,或者更好的整体实现


    我知道,但它对于我们的需求来说太有限了。

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

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

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


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

    您看过RickardÖberg使用Qi4J在Java中执行DCI和REST的示例了吗。我相信他使用URI结构来构建上下文,例如请求本身携带了在服务器上重新构建上下文所需的所有信息。此外,您可能希望尝试将此内容发布到对象组合google组。在cookie中存储上一步可能会有所帮助?当前上下文已通过cookie存储在会话中。我不知道存储前一步会给这种情况增加什么。在另一个浏览器窗口中执行某些操作也会使它变得无用。对我来说,命名空间URL是良好的restful编译器,因为如果您处于搜索上下文或提交上下文中,它不是相同的ressource。资源是相同的,但您可以使用它做什么取决于上下文。但也许你是对的。我只是对REST不太确定,不知道名称空间是否兼容;更重要的是,它是否会对我们试图提供的API的使用产生负面影响,首先是让应用程序RESTful。
    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