我从
this blog post开始学习了大约
Data,context,and interaction(DCI).着迷于这个概念,我努力将其构建到我的下一个Rails应用程序中.由于DCI与MVC协同工作,我认为在同一时间使API变得不那么难.所以我做了一个RESTful的资源,报告并用各种上下文进行扩展.在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
注意除了控制器上下文之外,我还扩展了一个角色的current_user.
以下是它的工作原理:
>用户登录.
>用户的角色是RegisteredUser.
> RegisteredUser的默认上下文是Search(在/app/roles/registered_user.rb中定义).
>在搜索范围内,用户只能查看已发布的报告.
>用户按“创建新报表”按钮,将上下文更改为“提交”并存储在current_user的会话中.
>然后用户通过多步骤的形式继续提交报告.
>每次用户通过单击/app/contexts/submission.rb上下文处理该操作的形式保存报告.
还有其他几个环境(评论,社论等)和角色(共同作者,编辑者等).
到目前为止,这种方法在很大程度上是有效的.但有一个缺陷:当用户打开多个浏览器窗口并在其中一个更改上下文时,所有其他窗口将处于错误的上下文中.如果用户位于多步骤窗体的中间,然后在“搜索”上下文中打开一个窗口,这可能是一个问题.当他切换回窗体并点击“下一步”时,控制器将执行由搜索上下文而不是提交上下文定义的动作.
有两种可能的方式,我可以想到:
>使用上下文名称命名报告资源.所以用户会访问URL,如/ search / reports和/ submission / reports / 1.这对我来说似乎不是RESTful,我宁可保持URL尽可能干净.
>将上下文名称放在隐藏的字段中.该方法要求开发人员记住将隐藏的字段放在网站上的每个表单中,并且它不适用于GET请求.
我知道this project,但它对我们的需求太有限.