Rails – 从我的观点中删除计算结果?

目前我在我的观点中进行了一些计算,当然这是一件坏事:

 ....  ....  

我正在研究能够帮助我重构上述问题的方法。

一件事是将计算移动到我的控制器

 @category_sum = @transaction.sum("amount_cents") 

这可能是一个更好的解决方案,但你知道。 不完美。

由于我有很多用户,我不知道如何将计算器逻辑移动到我的模型中。 所以我想我可能需要使用一个新类,创建一堆方法(总和,平均等)并在视图中使用它们? 我是在正确的轨道上吗? 非常感谢有关如何重构我的代码以及设计和实现此类的任何建议。

隔离视图逻辑的一个意思是使用演示者。

演示者允许您执行以下操作:

 <% categories.each do |c| %> .... <% present c do |category| %> <%= category.transaction_sum %> <% end %> .... <% end %> 

然后,您在app/presenters/category_presenter.rb有一个演示app/presenters/category_presenter.rb

 class CategoryPresenter < BasePresenter presents :category def transaction_sum category.transactions.sum("amount_cents") end end 

当然,如果您在该演示者中有许多方法,最好使用它(但是一旦开始减少视图逻辑,就可以快速填充演示者)。

这里使用的实现依赖于此pro railscast中描述的内容 。 基本思想就是拥有一个#present帮助器,它根据对象类推断出一个类名,加载并初始化正确的presenter类。

另一个流行的替代方案是使用drapper ,它使用装饰器的概念,但是演示者基本上是装饰器。

您看到的主要代码气味称为Demeter法则 (与许多编程“法则”一样,您应该将其视为“Demeter指南”)。

您可以做的是将实际计算步骤移动到类别的方法中,例如

 class Category < ActiveRecord::Base def transaction_amount transactions.sum("amount_cents") end end <% categories.each do |c| %> .... <%= c.transaction_amount %> .... <% end %> 

从技术上讲,在渲染视图时仍然会执行计算,但是计算总和量的逻辑不再在视图本身内部。 现在关注的所有视图都是它可以将消息transaction_amount发送到类别对象。 这也为您提供了为总和添加缓存的空间,或者让您停止传递实际记录,而是传递静态对象(不是ActiveRecord模型),这些对象来自执行总和的某些代码。更有效率的方式。