我有一个很老的模板系统写在ERB之上.它依赖于存储在数据库中的ERB模板.这些是阅读和渲染.当我想将数据从一个模板传递到另一个模板时,我使用:locals参数来实现Rails渲染方法.为了在某些模板中设置这些变量的默认变量,我使用定义的?方法,它只是告诉我是否已定义局部变量,如果不是,我使用默认值初始化它,如下所示:
unless defined?(perex) perex = true end
我正在将应用程序升级到最新的Rails,我看到一些奇怪的行为.基本上这有时是有效的(有时perex是未定义的),有时它不会(perex被定义并设置为nil).这种情况没有任何其他变化.
我有两个问题:除了使用定义之外还有更好的方法吗?这证明是不可靠的(在顶级Rails 1.6上几年可靠)?这种方式不应该导致我重写所有模板.我一直在浏览Ruby文档并且无法找到任何有关已定义的内容?方法.它被弃用了还是我只是盲目的?
编辑:实际问题是由似乎是Ruby/eRB的错误造成的.有时,除非声明可行,但有时不行.奇怪的是,即使第二条线被执行,perex仍然没有留给世界其他地方.删除已定义?解决了这一点
第一:实际上,defined?
是一个运营商.
第二:如果我正确理解你的问题,那么这样做的方法就是用这个Ruby成语:
perex ||= true
perex
如果它是未定义的,那将分配true nil
.它并不完全是你的例子所做的,因为你的值不是在值的时候评估赋值nil
,但是如果你依赖它,那么在我看来,没有看到它,你就不会编写清晰的代码.
编辑:正如Honza所说,上述陈述将取代perex
它的价值false
.然后我建议以下重写最小行数:
perex ||= perex.nil? # Assign true only when perex is undefined or nil
如果在Rails模板中定义了本地,最安全的测试方法是:
local_assigns[:perex]
这在Rails API中有记录,并附带defined?
由于实现限制而无法使用的解释.
根据mislav的回答,我在Rails API中寻找该文档,并在Class ActionView :: Base中找到它(在"将局部变量传递给子模板"标题下).然而,这几乎不值得搜索,因为它几乎没有说错误而已.除了它推荐这种模式:
if local_assigns.has_key? :perex
考虑到mislav的原始答案和KenB的阐述,我认为以下是绝对最好的方法(虽然我愿意接受意见).如果原始哈希中不存在密钥,它会利用Ruby的Hash #fetch方法回退备用值.
perex = local_assigns.fetch(:perex, true)
这甚至比||=
大多数用户建议的方法更好,因为有时您会想要允许false
值.例如,以下代码永远不允许false
传入值:
perex = local_assigns[:perex] || true