Rails的Helper应该假设实例变量存在还是应该作为参数传递?

40

我想知道是否有一种特定的编程原则(Demeter?)支持这样一个理念,即Rails助手程序应该永远不使用控制器实例变量,而是应该将这些变量作为函数参数传入。例如,假设我的ChickensController#squawk操作创建了一个名为@egg的实例变量。此外,假设squawk视图调用了一个名为cockadoodledoo的助手程序,实现如下:

def cockadoodledoo
  @egg.to_s
end

@egg作为参数传递,这样视图调用cockadoodledoo(@egg),助手类似于:

def cockadoodledoo(egg)
  egg.to_s
end

希望在周五下午,你们中的一位开心的黑客能够无聊到提出一个答案。咕咕叫!

这个问题与此类似,但从未得到准确的回答。


哦,有这么多好的答案,只有一个勾选框可以选择...谢谢大家。 - ybakos
4个回答

35

将它们作为参数接收。否则,随着应用程序的成长,重构、故障排除等过程中很难跟踪实例变量在哪里被设置。

此外,我认为通常最好的做法是仅在初始模板中在视图中使用实例变量...然后从那里将变量传递到助手和其他部分。


1
有人知道这个最佳实践在哪里提到或者它叫什么名字吗? - ybakos
7
Fabio,我不同意你的看法。当然,在编程艺术中,我们不希望强制实施苛刻的规则,但是命名事物非常有价值。例如,“DRY原则”。 - ybakos

21

我认为你应该始终明确地将变量传递给你的辅助函数,原因有两个:

  • 你可以精确控制你所做的事情

  • 最重要的是,你可以测试你的辅助函数


4
我没有考虑到可测试性。哎呀,我是不是暴露了短板?(是的,我应该写更多的测试。) - ybakos
1
提高测试辅助函数的能力是关键所在。感谢明确指出这一点。 - kries

12

我不知道是否有任何命名的原则来支配这种事情,但我会传递一个参数。传递参数不仅会使您的辅助函数易于测试,应用程序的数据流也更容易跟踪,而且它还将允许您在单个实例以及列表中使用一个帮助程序;如果您传递一个参数,那么两者都可以:

<%= cockadoodledoo @egg %>

并且:

<% @eggs.each do |egg| %>
    <%= cockadoodledoo egg %>
<% end %>

不需要引入一个特殊的cockadoodledoo来处理@eggs中的列表,而不是单个@egg,代码将按预期工作。


8

由于帮助信息被混合到所有控制器中,因此可用于所有视图(包括部分视图和布局),因此建立清晰的契约 - 参数始终是明智的选择。

唯一的例外我能想到的是当一个实例变量也可用于所有视图和控制器,比如菜单或类似物品。


3
没什么原因,我只是很努力地想找一个(你知道,每个规则都有例外),但我想我可能用力过猛了。 - Fábio Batista

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接