渲染多个咖啡的模式

Posted

技术标签:

【中文标题】渲染多个咖啡的模式【英文标题】:Pattern to render multiple coffee 【发布时间】:2017-05-05 19:58:26 【问题描述】:

我有一个与userproject 模型相关的task 模型。

当我创建/更新任务时,我需要在视图中进行异步更新,不仅针对任务更改/添加,还针对项目和用户信息(因为其中一些数据也可能发生更改)。

我在控制器中有这个:

def create
  @task = Task.new(params[:task])
  @project = Project.find(params[:project_id])

  respond_to do |format|
    if @task.save
      format.html  redirect_to @task, notice: 'Task was successfully created.' 
      format.json  render json: @task, status: :created, location: @task 
    else
      format.html  render action: "new" 
      format.json  render json: @task.errors, status: :unprocessable_entity 
    end
  end
end

还有我的任务/create.js.coffee

# Update task table
$('#mytable').append("<%= j render(partial: 'tasks/task', locals:  t: @task ) %>")

# Update user data
$('.user-data').html("<%= j render(partial: 'users/user_widget', locals:  u: current_user ) %>")

# Update project data
$('.project-data').html("<%= j render(partial: 'projects/project_widget', locals:  p: @project ) %>")

而且效果很好。我看到 2 个问题:

在我添加的.js.coffee 的每次渲染中,我重复代码太多了。我复制完全相同的代码来更新项目和用户数据,在任务更新、任务销毁时,我会为可能影响用户和项目的新模型做同样的事情

在 tasks/create.js.coffee 中处理项目和用户数据似乎很奇怪

因此,我正在寻找一种更好的模式来处理这些东西,有什么想法吗?

编辑(澄清): 我认为实现这样的目标会更好:

tasks/create.js.coffee

# Update task table
$('#mytable').append("<%= j render(partial: 'tasks/task', locals:  t: @task ) %>")

UserData.refresh()
ProjectData.refresh()

但是,我不能这样做,因为我每次都需要渲染部分,所以我必须做一些奇怪的事情,比如将 html 部分传递给那些 refresh() 函数,它与以前的方式。 这只是我想到的一种方式,但如果有的话,我想听听你的想法。

【问题讨论】:

我不清楚你在问什么。你想避免什么? 我试图避免我在帖子中描述的这两个问题:不重复代码来更新与项目和用户相关的模型的每个咖啡中的项目和用户数据。并且没有在任务 js 中更新用户和项目的责任。虽然这些问题非常相关 @DaveNewton 看看我的编辑,它可能会澄清一些事情 【参考方案1】:

您可以渲染属于不同控制器的模板/动作。因此,您可以将 tasks/create.js.coffee 文件和使用相同代码的所有其他控制器操作(如用户和项目)保留在您将使用的 respond_to 块中:

format.json  render 'tasks/create' 

你甚至可以渲染一个特定的文件:

format.json  render file: "path/to/specific/file" 

这是一个链接,其中包含有关在 Rails 中渲染的更多信息:http://guides.rubyonrails.org/layouts_and_rendering.html#rendering-an-action-s-template-from-another-controller

【讨论】:

我知道,但这并不能解决我的问题,因为这是我已经在做的事情。我的代码正在渲染任务/create.js.coffee。问题是该文件负责处理与任务不完全相关的多个视图更新。不过,非常感谢您的帮助 抱歉造成误会。我能想到的唯一另一种处理方法是让控制器响应 json 信息(而不是呈现 javascript)并使用 jQuery ajax 成功回调来更新页面上的信息。然后,您将拥有一个文件来处理所有页面更新。你甚至可以创建像UserData.refresh()ProjectData.refresh() 这样的通用函数,但它们都在javascript 中,而不是通过控制器渲染。我不认为你现在的做法有那么糟糕或非常规,这些只是其他选择。【参考方案2】:

对于任何可能对此问题的答案感兴趣的人,我发现 Garber-Irish 模式 是解决我的问题的好方法。

您可以在此处阅读更多相关信息: https://www.viget.com/articles/extending-paul-irishs-comprehensive-dom-ready-execution

甚至还有宝石:https://github.com/tonytonyjan/gistyle

使用此模式,您可以为 HTTP 请求创建执行上下文。例如,您可以在每个 js 控制器上使用 afterCreate() 方法,并且根据您的 HTTP 请求的创建位置,您可以触发不同的事件。

这允许使用多态答案来更新视图。

【讨论】:

以上是关于渲染多个咖啡的模式的主要内容,如果未能解决你的问题,请参考以下文章

模板模式——星巴克泡茶泡咖啡例题

模板模式——星巴克泡茶泡咖啡例题

设计模式之装饰模式的复习

9.装饰着模式

Java设计模式之装饰者模式

设计模式 | 工厂模式