在rails部分模板中可选的局部variables:我如何摆脱(定义的?foo)混乱?

我一直是个不好的孩子,在局部模板中使用下面的语法来为局部variables设置默认值,如果在渲染局部variables的时候,

<% foo = default_value unless (defined? foo) %> 

这似乎工作正常,直到最近,当(无缘无故我能辨别)非传递variables开始performance,如果他们已被定义为零(而不是未定义)。

正如在SO上各种有帮助的人所指出的, http : //api.rubyonrails.org/classes/ActionView/Base.html表示不要使用

 defined? foo 

而是使用

 local_assigns.has_key? :foo 

我试图修改我的方法,但是这意味着改变了很多模板。

可以/应该提前充电,并在所有模板中进行此更改? 有什么需要注意的技巧吗? 我需要多努力testing每一个?

我这样做:

 <% some_local = default_value if local_assigns[:some_local].nil? %> 

由于local_assigns是一个散列,你也可以使用可选的default_value 获取 。

 local_assigns.fetch :foo, default_value 

如果没有设置foo ,这将返回default_value

警告:

default_value是一个方法时,要小心local_assigns.fetch :foo, default_value ,因为它将被调用,以便将其结果传递给fetch

如果您的default_value是一个方法,您可以将其封装在一个块中: local_assigns.fetch(:foo) { default_value }以防止在不需要时调用它。

怎么样

 <% foo ||= default_value %> 

这说“使用foo如果它不是零或真实的,否则分配给foo的default_value

我想这应该在这里重复(从http://api.rubyonrails.org/classes/ActionView/Base.html ):

如果您需要查明某个局部variables是否在特定的渲染调用中被赋值,则需要使用以下模式:

 <% if local_assigns.has_key? :headline %> Headline: <%= headline %> <% end %> 

testing使用定义? 标题将无法正常工作。 这是一个实施限制。

我知道这是一个古老的线程,但这是我的小小贡献:我将在部分条件内使用local_assigns[:foo].presence 。 然后我只在需要渲染调用时设置foo

 <%= render 'path/to/my_partial', always_present_local_var: "bar", foo: "baz" %> 

看看这里的官方Rails指南 。 从RoR 3.1.0起有效。

我认为更好的select,允许多个默认variables:

 <% options = local_assigns.reverse_merge(:include_css => true, :include_js => true) %> <%= include_stylesheets :national_header_css if options[:include_css] %> <%= include_javascripts :national_header_js if options[:include_js] %> 

这是巴勃罗答案的衍生物。 这允许我设置一个默认('full'),最后在local_assigns和一个实际的局部variables中设置'mode'。

HAML /苗条:

 - mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full') 

ERB:

 <% mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full') %> 

在我的情况下,我使用:

 <% variable ||= "" %> 

在我的部分。
我不知道,如果这是好的,但我的确定

更直观,更紧凑:

<% some_local = default_value unless local_assigns[:some_local] %>

如果您不想每次调用局部variables时都使用局部variables,则可以这样做:

 <% local_param = defined?(local_param) ? local_param : nil %> 

这样可以避免undefined variable错误。 这将允许你使用/不使用局部variables来调用你的局部variables。

可以创build一个助手看起来像这样:

 somearg = opt(:somearg) { :defaultvalue } 

执行如下所示:

 module OptHelper def opt(name, &block) was_assigned, value = eval( "[ local_assigns.has_key?(:#{name}), local_assigns[:#{name}] ]", block.binding) if was_assigned value else yield end end end 

查看我的博客 ,了解有关如何以及为什么

请注意,此解决scheme确实允许您传递nil或false作为值而不会被覆盖。