我一直是个坏孩子,在我的局部模板中使用以下语法来设置局部变量的默认值,如果一个值没有显式地定义在:locals散列中,当呈现局部——时
<% foo = default_value unless (defined? foo) %>
这似乎工作得很好,直到最近(不知道为什么我能看出),未传递的变量开始表现得好像它们被定义为nil(而不是未定义)。
正如SO上许多乐于助人的人指出的那样,http://api.rubyonrails.org/classes/ActionView/Base.html说不要使用
defined? foo
而是使用
local_assigns.has_key? :foo
我正试图改变我的方式,但这意味着要改变很多模板。
我可以/应该直接在所有模板中进行这种更改吗?有什么诡计需要我注意吗?我需要多努力地测试每一个?
helper可以被创建成这样:
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
详见我的博客。
注意,这个解决方案允许你传递nil或false作为值而不被覆盖。
由于local_assign是一个哈希值,您还可以将fetch与可选的default_value一起使用。
local_assigns.fetch :foo, default_value
如果foo没有设置,它将返回default_value。
警告:
小心使用local_assignments。当default_value是一个方法时,它将被调用,以便将其结果传递给Fetch。
如果你的default_value是一个方法,你可以把它包装在一个块中:local_assignments .fetch(:foo) {default_value}来防止它在不需要的时候被调用。