我一直是个坏孩子,在部分模板中使用以下语法来设置局部变量的默认值,如果在渲染部分时未在:locals哈希中显式定义值 -
<% foo = default_value unless (defined? foo) %>
直到最近,这似乎工作正常(当时我无法辨别)未通过的变量开始表现得好像它们被定义为nil(而不是未定义)。
正如SO上各种乐于助人的人所指出的,http://api.rubyonrails.org/classes/ActionView/Base.html说不使用
defined? foo
而是使用
local_assigns.has_key? :foo
我正在尝试修改我的方法,但这意味着要更改很多模板。
可以/我应该提前充电并在所有模板中进行此更改吗?我需要注意什么诡计?我需要多努力地测试每一个?
答案 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)
有可能,但是您必须在范围中声明默认值。
变量是要替换的词。
# 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作为值而不会被覆盖。