Ruby-on-rails Rails:部分应该知道实例变量吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2503838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:26:21  来源:igfitidea点击:

Rails: Should partials be aware of instance variables?

ruby-on-railsrubypartialactionview

提问by Alexandre

Ryan Bates' nifty_scaffolding, for example, does this

例如,Ryan Bates 的 nifty_scaffolding 就是这样做的

edit.html.erb

编辑.html.erb

<%= render :partial => 'form' %>

new.html.erb

新的.html.erb

<%= render :partial => 'form' %>

_form.html.erb

_form.html.erb

<%= form_for @some_object_defined_in_action %>

That hidden state makes me feel uncomfortable, so I usually like to do this

那个隐藏状态让我感觉不舒服,所以我通常喜欢这样做

edit.html.erb

编辑.html.erb

<%= render :partial => 'form', :locals => { :object => @my_object } %>

_form.html.erb

_form.html.erb

<%= form_for object %>

So which is better: a) having partials access instance variablesor b) passing a partial all the variables it needs?

那么哪个更好:a)让partials访问实例变量b)传递一个partial它需要的所有变量?

I've been opting for b) as of late, but I did run into a little pickle:

我最近一直在选择 b),但我确实遇到了一点泡菜:

some_action.html.erb

some_action.html.erb

<% @dad.sons.each do |a_son| %>
<%= render :partial => 'partial', :locals => { :son => a_son } %>
<% end %>

_partial.html.erb

_partial.html.erb

The son's name is <%= son.name %>
The dad's name is <%= son.dad.name %>

son.dad makes a database call to fetch the dad! So I would either have to access @dad, which would be going back to a) having partials access instance variablesor I would have to pass @dad in locals, changing render :partial to <%= render :partial => 'partial', :locals => { :dad => @dad, :son => a_son } %>, and for some reason passing a bunch of vars to my partial makes me feel uncomfortable. Maybe others feel this way as well.

son.dad 调用数据库来获取父亲!所以我要么必须访问@dad,这将返回到a) 有部分访问实例变量,或者我必须在本地传递@dad,将 render :partial 更改为 <%= render :partial => 'partial' , :locals => { :dad => @dad, :son => a_son } %>,出于某种原因,将一堆变量传递给我的部分让我感到不舒服。也许其他人也有这种感觉。

Hopefully that made some sense. Looking for some insight into this whole thing... Thanks!

希望这是有道理的。寻找对整个事情的一些见解......谢谢!

回答by ryanb

In recent versions of Rails it is quite a bit easier to render partials and pass locals to them. Instead of this.

在最新版本的 Rails 中,渲染局部变量并将局部变量传递给它们要容易得多。而不是这个。

<%= render :partial => 'form', :locals => { :item => @item } %>

You can do this.

你可以这样做。

<%= render 'form', :item => @item %>

I don't do this in the Nifty Scaffold generator to keep backwards compatibility, but I'll change this in a future release.

我不会在 Nifty Scaffold 生成器中这样做以保持向后兼容性,但我会在未来的版本中改变这一点。

As for whether it's acceptable to use instance variables in partials. I think it is. In all practicality, what is the downside? Certainly things can get out of hand if you aren't consistent, but I like to apply these guidelines.

至于在partials中使用实例变量是否可以接受。我觉得是这样的。在所有实用性中,缺点是什么?当然,如果您不一致,事情可能会失控,但我喜欢应用这些准则。

  1. Never create an instance variable just to share it between partials. Usually this means you will only be sharing the controller resource object.

  2. If the partial is the same name as the resource, pass it as a local with <%= render @item %>.

  3. If the partial will be shared across multiple controllers then only use locals.

  1. 永远不要创建一个实例变量只是为了在部分之间共享它。通常这意味着您将只共享控制器资源对象。

  2. 如果部分与资源同名,则将其作为带有<%= render @item %>.

  3. 如果部分将在多个控制器之间共享,则仅使用本地人。

This is what works well for me anyway.

无论如何,这对我来说很有效。

Bonus tip:if you find yourself passing in a lot of locals into a partial and you want some of them to be optional, create a helper method which renders the partial. Then always go through the helper method so you can make a clean interface with optional args for rendering the partial.

额外提示:如果您发现自己将很多局部变量传递给局部变量,并且希望其中一些是可选的,请创建一个渲染局部变量的辅助方法。然后总是通过 helper 方法,这样你就可以使用可选的 args 制作一个干净的界面来呈现部分。

回答by Edward Anderson

Using @instance_variables in partials is bad design.

在部分中使用 @instance_variables 是糟糕的设计。

Using instance variable in partials works, but it can make it harder to maintain applications if changes are ever needed.

在部分中使用实例变量是有效的,但如果需要更改,它会使维护应用程序变得更加困难。

The downside of using instance variables in partials is that you create a dependency in the partial to something outside the partial's scope (coupling). This makes the partial harder to reuse, and can force changes in several parts of the application when you want to make a change in one part.

在部分中使用实例变量的缺点是您在部分中创建了对部分范围之外的东西的依赖(耦合)。这使得部分更难重用,并且当您想对一个部分进行更改时,可能会强制更改应用程序的多个部分。

Partials that use instance variables:

使用实例变量的部分:

  • must change when the instance variable in any controller that uses the partial changes either the instance variable name or its type or data structure
  • cause all controller actions that use the partial to change in the same way at the same time when there are changes to how the instance variable is used
  • discourage reuse, as they can only easily be reused in actions that set up instance variables with the same name and data
  • 当使用部分的任何控制器中的实例变量更改实例变量名称或其类型或数据结构时,必须更改
  • 当实例变量的使用方式发生变化时,导致所有使用部分的控制器动作同时以相同的方式变化
  • 不鼓励重用,因为它们只能在设置具有相同名称和数据的实例变量的操作中轻松重用

Instead, pass locals to the partials:

相反,将局部变量传递给局部变量:

<%= render 'reusable_partial', :item => @item %>

Now, because the partial only references itemand not @item, the action that renders the view that renders the reusable_partial is free to change without affecting the reusable_partial and the other actions/views that render it:

现在,因为部分只引用item而不是@item,呈现呈现 reusable_partial 的视图的操作可以自由更改,而不会影响 reusable_partial 和呈现它的其他操作/视图:

<%= render 'reusable_partial', :item => @other_object.item %>

Also, this can be reused in contexts where there is no @item:

此外,这可以在没有@item 的上下文中重用:

<%= render 'reusable_partial', :item => @duck %>

If my @duckchanges in the future and no longer quacks like reusable_partial expects it to (the object's interface changes), I can also use an adapter to pass in the kind of item that reusable_partial expects:

如果我@duck将来更改并且不再像 reusable_partial 期望的那样嘎嘎作响(对象的接口更改),我还可以使用适配器传递 reusable_partial 期望的项目类型:

<%= render 'reusable_partial', :item => itemlike_duck(@duck) %>

Always?

总是?

There are plenty of situations where you probably don't need de-coupled partials like this, and it's easier in the short run to use an instance variable. However, it's hard to predict the future needs of your application.

在很多情况下,您可能不需要像这样解耦部分,并且在短期内使用实例变量更容易。但是,很难预测应用程序的未来需求。

As such, this makes for good general practice while having relatively low cost.

因此,这是一种良好的通用做法,同时成本相对较低。

回答by Vezquex

You can have it both ways. At the top of your partial:

你可以同时拥有它。在你的部分的顶部:

<% item ||= @item %>

That way, it works with or without passing the local variable, providing a sane default, but not inhibiting alternate usage of the partial.

这样,无论是否传递局部变量,它都可以工作,提供合理的默认值,但不会禁止部分的替代使用。

回答by konung

I vote for a) for a very specific reason -- DRY! If you start passing a variable like that, the next thing you know it's a mess. Let's say you need to change the way your variable is named or something else about it. You'll need to go to ALL your views and change them instead of ONE partial.

我投票赞成 a) 一个非常具体的原因——干!如果你开始传递这样的变量,接下来你就会知道它是一团糟。假设您需要更改变量的命名方式或其他相关内容。您需要转到所有视图并更改它们而不是一个部分。

Also, if you change your partial it will change on all your views, so you'll need to know which views are used. A proper IDE should be able to help you with that, but I also like having a small comment section at the top of the view where I just mention where it's used and why. This helps another programmer and it helps you to remember in case you need to come back to a partial and modify. But the whole point of the partial is to call it WITHOUT having to pass anything from the view, so that you don't have to modify all places where partial is called from if that variable changes somehow.

此外,如果您更改您的部分,它会更改您的所有视图,因此您需要知道使用了哪些视图。一个合适的 IDE 应该能够帮助你解决这个问题,但我也喜欢在视图顶部有一个小的评论部分,我只是提到它的使用位置和原因。这有助于另一个程序员,它可以帮助您记住,以防您需要返回部分并进行修改。但是 partial 的重点是调用它而不必从视图中传递任何内容,这样如果该变量以某种方式发生变化,您就不必修改调用 partial 的所有位置。

Ultimately this is a design choice, and to be honest unless you are running a facebook the extra lookup you do is not that big of a deal, but it's just not very DRY.

最终,这是一个设计选择,老实说,除非您正在运行 Facebook,否则您所做的额外查找并不是什么大问题,但它并不是很 DRY。

P.S.: Just thought about it. You can actually abstract the way you call partial in a helper method, so then if the way you call your partial needs to change, you just need to modify one place.

PS:只是想了想。你实际上可以抽象出你在辅助方法中调用partial的方式,所以如果你调用partial的方式需要改变,你只需要修改一个地方。