Rails:重构、视图、助手:这一切是如何结合在一起的?
警告:这里是菜鸟。
我知道这是一个微不足道的主题,但我很难弄清楚如何通过将其中的一部分转移到助手中来简化我的视图。例如,我一直读到您观点中的条件是提取为助手的主要候选者,但我无法真正找到这方面的示例,并且我实现这一目标的尝试失败了。
例如,假设我有:
#index.html.erb
<% for beast in @beasts do -%>
<% if beast.dead? -%>
<%= beast.body %>
<%= link_to "bury", bury_beast_path( :id => beast.id ) %>
<% else -%>
<%= beast.body %>
<%= link_to "kill!", kill_beast_path( :id => beast.id ) %>
<% end -%>
<% end -%>
在我看来,这让我有点恼火,但我到底如何才能将其转移给助手呢?如果可能的话,进一步简化它。 (我在某处读到过,条件语句很糟糕,但我无法理解如何在没有它们的情况下编写任何东西。)
另一个例子:我需要使用 id
我的 body
标签格式controller_action
。到目前为止我得到的最好的结果是:
#index.html.erb
<body id="<%= controller_action %>">
……而且……
#application_helper.rb
def controller_action
@id = @controller.controller_name + "_" + @controller.action_name
end
我不是专家,但即使对我来说这仍然很丑陋。
为了让事情变得更复杂,Ryan Singer 说了一些我喜欢的话:将 ERB 视为图像标签,使用助手来“揭示意图”。然后在下一次呼吸中说你不应该在帮助程序中使用 HTML,因为那是通往地狱的道路。搞什么?两者如何兼容?如果已经到了可以在视图中声明行为的地步,那么肯定应该有很多 HTML 需要在幕后渲染?我无法把握它。
所以,基本上就是这样。如果有人能就此分享一些想法,或者向我指出一些关于该主题的深入读物,我将不胜感激——我发现网络上的报道非常薄弱。我已经用谷歌搜索得筋疲力尽了,但谁知道呢。
Warning: Noob here.
I know this is a trivial subject but I'm having a lot of difficulty in figuring out how exactly I can simplify my views by moving parts of them into helpers. For example, I've always read that conditionals in your views are prime candidates for extraction into helpers, but I couldn't really find examples of this, and my attempts to achieve this failed.
For example, suppose I have:
#index.html.erb
<% for beast in @beasts do -%>
<% if beast.dead? -%>
<%= beast.body %>
<%= link_to "bury", bury_beast_path( :id => beast.id ) %>
<% else -%>
<%= beast.body %>
<%= link_to "kill!", kill_beast_path( :id => beast.id ) %>
<% end -%>
<% end -%>
It annoys me a little to have this in my view, but how exactly could I move this to a helper instead? And further simplify it, if possible. (I've read somewhere that conditionals are bad but it's just beyond me how you could program anything without them.)
Another example: I need to id
my body
tags with the format controller_action
. The best I've got so far is this:
#index.html.erb
<body id="<%= controller_action %>">
…and…
#application_helper.rb
def controller_action
@id = @controller.controller_name + "_" + @controller.action_name
end
I'm no expert, but that's still ugly even to me.
To make things more complicated, Ryan Singer said something I liked: to treat ERB like an image tag, using helpers to "reveal intention". Then in the next breath saying that you should have no HTML in helpers for that is the way to hell. WTF? How are both things compatible? If it's come to the point where you can just declare behaviors in the view, surely there should be a lot of HTML to be rendered behind the scenes? I can't grasp it.
So, that's basically it. I'd appreciate if anyone could share some thoughts on this, or point me to some good in depth reading on the subject – which I've found to have a really weak coverage on the web. I've already googled it to exhaustion but who knows.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
重构使您的视图更易于维护。问题在于选择重构代码的去向。
您的两个选择是partials和helpers。没有一成不变的规则规定哪些应该在哪里使用。有一些准则正在流传,例如声明帮助程序不应包含 HTML 的准则。
一般来说,部分代码比 ruby 更适合 HTML/ERB/HAML 较多的重构部分。另一方面,助手用于具有最少 HTML 的 ruby 代码块或从参数生成简单的 HTML。
然而,我不同意助手不应该包含任何 HTML 的观点。一点点就可以了,只是不要过度。帮助程序的处理方式阻碍了它们用于生成大量 HTML。这就是为什么建议您的帮助程序包含最少量的 HTML。如果您查看 Rails 附带的助手的源代码,您会发现它们中的大多数都会生成 html。少数没有的主要用于生成参数和评估常见条件。
例如,任何形式帮助器或 link_to 变体都适合第一种形式的帮助器。而像 url_for 和logged_in 这样的东西?各种认证模型提供的都是第二类。
这是我用来确定是否将视图中的代码分解为部分代码或帮助程序的决策链。
我将使用您要重构的代码作为示例:
我将以这种方式重构问题中的视图:
app/helpers/beast_helper.rb:
app/views/beasts/_beast.html.erb:
app /views/beasts/index.html.erb:
它在技术上更复杂,因为它总共有 3 个文件和 10 行,而不是 1 个文件和 10 行。现在,视图只有 3 行,分布在 2 个文件中。最终结果是你的代码更加干燥。允许您在其他控制器/操作/视图中重用部分或全部内容,以最小的增加复杂性。
至于你的身体标签ID。您确实应该使用 content_for/yield。对于那种事情。
app/views/layouts/application.html.erb
app/views/beasts/index.html.erb
这将允许您在任何需要它的视图中覆盖正文的 id。例如:
app/views/users/preferences.html.erb
Refactoring makes your views easier to maintain. The problem is choosing where the refactored code goes.
Your two choices are partials and helpers. There's no stone-set rules dictating which should be used where. There are a couple of guidelines floating around like the one stating that helpers should not contain HTML.
Generally partials are better suited for refactoring sections that are more HTML/ERB/HAML than ruby. Helpers on the other hand are used for chunks of ruby code with minimal HTML or generating simple HTML from parameters.
However, I don't agree with the sentiment that helpers should contain no HTML at all. A little is ok, just don't over do it. The way helpers are processed hinder their use for producing large amounts of HTML. Which is why it's suggested that your helpers contain minimal amounts of HTML. If you look at the source the helpers that ship with rails you will notice that most of them generate html. The few that don't, are mainly used to generate parameters and evaluate common conditions.
For example, any of the form helpers or link_to variants fit the first form of helpers. While things like url_for and logged_in? as supplied by various authentication models are of the second kind.
This is the decision chain I use to determine whether to factor code from a view into a partial or helper.
I'm going to use the code you're looking to refactor as an example:
I would refactor the view in the question this way:
app/helpers/beast_helper.rb:
app/views/beasts/_beast.html.erb:
app/views/beasts/index.html.erb:
It's technically more complicated, because it's 3 files, and 10 lines total as opposed to 1 file and 10 lines. The views are now only 3 lines combined spread over 2 files. The end result is your code is much more DRY. Allowing you to reuse parts or all of it in other controllers/actions/views with minimal added complexity.
As for your body tag id. You should really be using content_for/yield. For that kind of thing.
app/views/layouts/application.html.erb
app/views/beasts/index.html.erb
This will allow you to override the id of the body in any view that requires it. Eg:
app/views/users/preferences.html.erb
我要做的第一件事是:
我所做的是将野兽的渲染分离为使用集合语义的部分。
然后我将显示杀死/埋葬链接的逻辑移至野兽助手中。这样,如果您决定添加另一个操作(例如,“起死回生”),您只需更改助手即可。
这有帮助吗?
The first thing I'd do would be this:
What I've done is separate out the rendering of the beast into a partial which uses collection semantics.
Then I've moved the logic for showing the kill/bury links into a beast helper. This way if you decide to add another action (for example, 'bring back from dead'), you'll only have to change your helper.
Does this help?
第三种选择是使用 Cells gem 中的视图模型。这是一个非常流行的框架,它将面向对象引入了 Rails 的视图层。
然后,您使用助手(在视图或控制器中)渲染视图模型。
就这样!您可以在单独的测试中隔离该单元格进行测试。单元格还为您提供视图渲染、视图继承等等。
例如,您可以使用
kill
链接的视图。这呈现出细胞的杀手级视野。
请注意视图的位置,它很好地打包到单元目录中。
是的,单元格可以执行 HAML 以及
AbstractController
支持的任何其他模板引擎。A third choice is to use a view model from the Cells gem. This is a very popular framework that brings object-orientation to the view layer in Rails.
You then render a view model using a helper (in the view or controller).
That's all! You can test this cell isolated in a separate test. Cells also give you view rendering, view inheritance and many more things.
As an example, you could use a view for the
kill
link.This renders the cell's killer view.
Note the location of the view, it's nicely packaged into the cell directory.
And, yes, cells can do HAML and any other template engine supported by
AbstractController
.另一个策略是根本不使用模板和助手。
对于渲染,您可以:
这背后的想法是助手和rails erb模板系统不利用OOP,因此最终您无法定义根据每个控制器/请求的需求专门化的一般行为;通常情况下,人们最终会重写看起来非常相似的代码块,从维护的角度来看,这并不是很好。
然后,如果您仍然需要一些辅助方法(例如 form_tag、h、raw 等),您只需将它们包含在您的控制器/专用视图类中。
看看这个:rails-misappregnons-helpers-are-shit 一篇有趣但有用的文章。
编辑:为了听起来不像是一个彻底的混蛋,我想说实现这一点取决于您的应用程序应该有多大,以及您需要更新代码的频率。另外,如果您将设计委托给非程序员,他/她很可能会在深入研究您的代码之前参加一些编程课程,这无疑比模板语法更难以直接理解。
Another startegy would be to not use templates and helpers at all.
For rendering you could :
The idea behind this is that helpers and rails erb templating system don't take advantage of OOP, so that at the end of the day you can't define general behaviours that you'll specialize according to each controller's/request's needs; more often than not one ends up rewriting very similar looking chunks of code, which is not very nice from a maintenance standpoint.
Then if you still need some helper methods (eg. form_tag, h, raw, ...) you only have to include them in your controller / dedicated view class.
See this : rails-misapprehensions-helpers-are-shit for a fun but useful article.
EDIT: to not sound like a complete douche, I'd say implementing this depends on how big your application is supposed to be, and how often you're going to have to update your code. Plus, if you're delegating the design to a non-programmer, he/she may well be in for some programming courses before digging into your code, which admittedly would be less directly understandable than with templates syntax.