rails部分模板中的可选局部变量:如何摆脱(定义的?foo)混乱局面?

时间:2010-01-13 21:55:16

标签: ruby-on-rails partials

我一直是个坏孩子,在部分模板中使用以下语法来设置局部变量的默认值,如果在渲染部分时未在:locals哈希中显式定义值 -

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

直到最近,这似乎工作正常(当时我无法辨别)未通过的变量开始表现得好像它们被定义为nil(而不是未定义)。

正如SO上各种乐于助人的人所指出的,http://api.rubyonrails.org/classes/ActionView/Base.html使用

defined? foo

而是使用

local_assigns.has_key? :foo

我正在尝试修改我的方法,但这意味着要更改很多模板。

可以/我应该提前充电并在所有模板中进行此更改吗?我需要注意什么诡计?我需要多努力地测试每一个?

12 个答案:

答案 0 :(得分:308)

我这样做:

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

答案 1 :(得分:147)

由于local_assigns是哈希值,您还可以将fetch与可选default_value一起使用。

local_assigns.fetch :foo, default_value

如果default_value未设置,则会返回foo

警告:

local_assigns.fetch :foo, default_value是一种方法时,请注意default_value,因为无论如何它都会被调用,以便将结果传递给fetch

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

答案 2 :(得分:81)

怎么样

<% foo ||= default_value %>

这表示“如果不是nil或true则使用foo。否则将default_value分配给foo”

答案 3 :(得分:10)

我认为这应该在这里重复(来自http://api.rubyonrails.org/classes/ActionView/Base.html):

如果您需要确定某个局部变量是否已在特定渲染调用中分配了值,则需要使用以下模式:

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

使用已定义的测试?标题不起作用。这是一个实施限制。

答案 4 :(得分:4)

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

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

看看te official Rails guide here。从RoR 3.1.0开始。

答案 5 :(得分:4)

就我而言,我使用:

<% variable ||= "" %>

在我的部分。
我不知道这是否好,但我的确可以

答案 6 :(得分:1)

我认为这是一个允许多个默认变量的更好选项:

<% 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] %>

答案 7 :(得分:1)

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

HAML /苗条:

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

ERB:

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

答案 8 :(得分:0)

更直观,更紧凑:

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

答案 9 :(得分:0)

如果您不想在每次调用时将局部变量传递给局部变量,请执行以下操作:

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

这样可以避免undefined variable错误。这将允许您使用/不使用局部变量调用部分。

答案 10 :(得分:0)

Ruby 2.5

Erb

有可能,但是您必须在范围中声明默认值。

变量是要替换的词。

# index.html.erb
...
<%= render 'some_content', VARIABLE: false %>
...

# _some_content.html.erb
...
<% VARIABLE = true if local_assigns[:VARIABLE].nil? %>
<% if VARIABLE %>
    <h1>Do you see me?</h1>
<% end %>
...

答案 11 :(得分:-6)

可以创建一个帮助器,如下所示:

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

有关如何以及为何的详细信息,请参阅my blog

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