12

我正在实现一个仪表板作为一个相对的 Rails 新手(更多的是一个基础设施的人)。仪表板将由多个页面组成,每个页面将包含多个图表/表格/等。对于模块化,我希望添加新图表或更改数据视图尽可能简单。

假设一页有 5 个不同的图表。我可以让控制器进行 5 次单独的数据查找,将所有相关数据保存在实例变量中,并渲染 5 个部分,每个部分都触及数据的子集。但似乎更模块化的是有一个“索引”控制器动作,它的渲染有一堆 div,并且对于每个 div,都有另一个控制器动作来进行数据查找并有一个关联的视图部分负责管理该数据的视图在 div 内。

因此,如果我要显示具有两个图表的网站仪表板页面,website/index将使用website/graph1website/graph2查找每个图表的数据,然后_graph1.html.erb使用_graph2.html.erb控制器数据来填写 div"graph1""graph2"等。

这是正确的设计吗?如果是,最简单的方法是什么?我有一个使用remote_functionwith:action => "graph1"来填写 div 的近似值,但我对它并不是 100% 满意。我怀疑我错过了 Rails 为我做的更简单的事情。

4

4 回答 4

10

版本 1:

我在生产中实际使用的简单方法:iframe。

大多数情况下,您实际上并不关心页面是否一次全部呈现并直接从服务器呈现,实际上交错加载会更好。

如果您只是将 iframe src'd 放到控制器的显示操作中,那么您就有一个非常简单的解决方案,不需要直接的跨控制器交互。

临:

  • 容易死
  • 适用于现有的表演动作等
  • 甚至可能更快,这取决于并行与顺序请求和内存负载等的节省

缺点:

  • 您不能总是轻松地将页面与任何内容一起保存
  • iframe 将脱离主机页面的 javascript 命名空间,因此如果它们需要,您可能需要为它们提供自己的简约布局;他们也无法影响其 iframe 之外的周围页面
  • 可能会更慢,具体取决于 ping 时间等
  • 如果页面上有许多这样的模块,则潜在的 n+1 效率错误

版本 2:

使用 JS 调用执行相同的操作,将 div 替换为部分内容,à la:

<div id="placeholder">
<%= update_page {|page| page['placeholder'].replace with some partial call here } %>

同上,除了:

临:

  • 不会将其锁定到 iframe 中,因此共享 JS 上下文等
  • 允许更好地处理故障情况

缺点:

  • 需要 JS 和占位符 div;稍微复杂一点

版本 3:

调用一大堆部分。但是,一旦您谈论诸如仪表板之类的事情,其中​​各个模块具有大量设置逻辑,这样做就会变得复杂。

有多种方法可以通过将这些东西变成“mixins”或类似的东西来解决这个问题,但 IMO 他们有点笨拙。

ETA:通过 mixins 实现它的方法是创建本质上是一个库文件,它实现了模块控制器的设置功能,包括在任何使用调用 'em 的东西的地方,并调用 'em。

但是,这有缺点:

  • 您必须知道哪些顶级控制器操作将导致包含这些模块的页面(如果这些确实是可能出现的小部件,例如依赖于用户偏好,那么您可能不容易)
  • 它并不能真正充当成熟的控制器
  • 它仍然混合了很多逻辑,你持有的东西需要知道它持有的东西
  • 你不能轻易地将它隔离到它自己的控制器中,因为它需要在一个库类型的文件/mixin 中

可以从另一个控制器调用一个控制器中的方法。然而,这是一个主要的痛苦,也是一个主要的kludge。您唯一应该考虑这样做的情况是:a)它们都是独立必需的控制器,并且b)它必须完全在后端运行。

我不得不这样做一次 - 主要是因为重构它的原因更加痛苦 - 我保证你不想去那里,除非你必须这样做。

概括

最好的方法恕我直言,如果你有足够复杂的东西需要大量设置 - 一个简单的 iframe 显示模块,传递一个参数告诉它使用极简布局(只是 CSS + JS 标题),因为它没有被显示作为自己的页面。

这使您可以保持事物完全独立,或多或少地像它们自己的完全正常的控制器一样运行(除了布局设置),保留正常的路线等。

如果您不需要大量设置,则只需使用部分,并将所需的任何内容作为局部变量传递。但是,如果您遇到诸如 n+1 效率错误之类的问题,这将开始变得脆弱……

于 2009-05-26T19:31:46.223 回答
7

你为什么不试试 Apotomo,这是 Rails 的有状态小部件:

一个教程如何构建一个简单的仪表板

于 2009-11-13T17:51:19.333 回答
1

您可以通过使用来实现这一点

渲染输出=渲染:动作=>“graph2”

但我个人可能会将代码包装在共享帮助程序中,或者在 lib 目录下编写您自己的“lib”,以便通过共享模板重用代码。请记住,除非您更改您的 route.rb 文件,否则定义的任何公共方法都可以通过

/控制器/动作/:id

还要记住关闭函数的布局 :layout => nil (或在控制器布局“graph”的顶部指定, :except => ["graph2"]

干杯

基督教

于 2009-05-26T16:36:44.377 回答
0

如果不按照您概述的方式使用 AJAX,我不知道有任何特殊的 Rails 技巧可以实现这一目标。

获得您寻求的模块化的最简单方法是将控制器代码的这些部分放入单独的方法中(例如set_up_graph1_dataset_up_graph2_data等),您只需从您的index操作中调用这些方法来设置视图的变量。

ApplicationController如果您希望它们可用于多个控制器,您可以将这些方法放入其中。

顺便说一句,Rails 早期确实有一个称为“组件”的功能,它可以让你完全按照你的要求做,而不必使用 AJAX。从您的角度来看,您可以只渲染另一个控制器操作,内联。但是,出于性能和设计理念的原因,此功能已被删除。

于 2009-05-26T13:11:12.263 回答