Rails:部分人员应该知道实例变量吗?

Ale*_*dre 63 ruby ruby-on-rails actionview partial

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

edit.html.erb

<%= render :partial => 'form' %>
Run Code Online (Sandbox Code Playgroud)

new.html.erb

<%= render :partial => 'form' %>
Run Code Online (Sandbox Code Playgroud)

_form.html.erb

<%= form_for @some_object_defined_in_action %>
Run Code Online (Sandbox Code Playgroud)

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

edit.html.erb

<%= render :partial => 'form', :locals => { :object => @my_object } %>
Run Code Online (Sandbox Code Playgroud)

_form.html.erb

<%= form_for object %>
Run Code Online (Sandbox Code Playgroud)

那么哪个更好:a)有部分访问实例变量b)传递部分所需的所有变量?

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

some_action.html.erb

<% @dad.sons.each do |a_son| %>
<%= render :partial => 'partial', :locals => { :son => a_son } %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

_partial.html.erb

The son's name is <%= son.name %>
The dad's name is <%= son.dad.name %>
Run Code Online (Sandbox Code Playgroud)

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

希望这有点道理.寻找对这整件事的一些见解......谢谢!

rya*_*anb 103

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

<%= render :partial => 'form', :locals => { :item => @item } %>
Run Code Online (Sandbox Code Playgroud)

你可以这样做.

<%= render 'form', :item => @item %>
Run Code Online (Sandbox Code Playgroud)

我不会在Nifty Scaffold生成器中执行此操作以保持向后兼容性,但我将在以后的版本中对此进行更改.

至于在partials中使用实例变量是否可以接受.我觉得是这样的.实际上,缺点是什么?如果你不一致,事情可能会失控,但我喜欢应用这些指导方针.

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

  2. 如果partial与资源名称相同,则将其作为local传递给<%= render @item %>.

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

无论如何,这对我来说都很有用.

额外提示:如果您发现自己将很多本地人传入某个部分,并且您希望其中一些是可选的,请创建一个辅助方法来渲染部分.然后总是通过辅助方法,这样你就可以使用可选的args创建一个干净的界面来渲染部分.

  • +1为"3.如果部分将在多个控制器之间共享,则只使用本地." (4认同)

Edw*_*son 43

在partials中使用@instance_variables是糟糕的设计.

在partials中使用实例变量可以工作,但如果需要更改,它可能会使维护应用程序变得更加困难.

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

使用实例变量的部分:

  • 当使用partial的任何控制器中的实例变量更改实例变量名称或其类型或数据结构时,必须更改
  • 当使用实例变量的方式发生更改时,会导致使用partial的所有控制器操作以相同的方式更改
  • 阻止重用,因为它们只能在设置具有相同名称和数据的实例变量的操作中轻松重用

而是将本地传递给部分:

<%= render 'reusable_partial', :item => @item %>
Run Code Online (Sandbox Code Playgroud)

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

<%= render 'reusable_partial', :item => @other_object.item %>
Run Code Online (Sandbox Code Playgroud)

此外,这可以在没有@item的情况下重复使用:

<%= render 'reusable_partial', :item => @duck %>
Run Code Online (Sandbox Code Playgroud)

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

<%= render 'reusable_partial', :item => itemlike_duck(@duck) %>
Run Code Online (Sandbox Code Playgroud)

总是?

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

因此,这具有良好的通用性,同时具有相对低的成本.


Vez*_*uex 5

你可以两种方式.在你的部分顶部:

<% item ||= @item %>
Run Code Online (Sandbox Code Playgroud)

这样,它可以在传递或不传递局部变量的情况下工作,提供合理的默认值,但不禁止部分的替代使用.

  • 这使得耦合完全不清楚.部分现在有两个合同. (2认同)