2008-10-26 29 views
26

我有一个相当旧的模板系统写在ERB之上。它依赖于存储在数据库中的ERB模板。那些被阅读和渲染。当我想将数据从一个模板传递到另一个模板时,我使用:locals参数来Rails渲染方法。为了在一些模板中设置这些变量的默认变量,我使用了定义的?方法简单地告诉我,如果局部变量定义;如果没有使用默认值初始化它是这样的:定义?方法在Ruby和Rails

unless defined?(perex) 
    perex = true 
end 

我升级应用最新的Rails,我看到一些奇怪的行为。基本上这有时会起作用(有时perex是未定义的),有时它不会(perex被定义并设置为零)。这发生在没有其他变化的情况下

我有两个问题: 除了使用定义之外,还有其他更好的方法吗?这证明是不可靠的(在顶级Rails 1.6上可靠几年)?这样的方式不应该导致我重写所有的模板。 我一直在浏览Ruby文档,无法找到关于定义的任何内容?方法。它已被弃用,还是我只是盲目的?

编辑:实际问题是由似乎是Ruby/eRB错误引起的。有时除非声明会起作用,但有时不会。奇怪的是,即使第二条线执行perex斯蒂尔留在世界其他地方。删除已定义的?解决了。

回答

36

第一个:实际上,defined? is an operator

二:如果我正确地理解你的问题,要做到这一点是与此红宝石成语:

perex ||= true 

,如果它是未定义或nil那将分配真实perex。这并不完全代表你的例子,因为当值为nil时,你不会评估任务,但如果你依赖那个,那么在我看来,如果没有看到它,那么你并没有写出清晰的代码。

编辑:正如Honza指出的那样,上述声明将取代perex的值,即false。然后,我提出以下改写的最小行数:

perex ||= perex.nil? # Assign true only when perex is undefined or nil 
+10

这是不正确的。 perex || = true与perex = perex ||相同如果它是未定义的,则将perex设置为true,否则为false。最后的情况会打破一切。 – Honza 2008-10-27 08:16:14

24

测试的最安全的方式,如果在Rails模板定义的本地是:

local_assigns[:perex] 

这是Rails API中记录以及由于实施限制而无法使用defined?的解释。

+1

如果perex的价值为假,该怎么办? – 2013-02-08 01:13:38

+0

你可以自己检查:) perex = true如果local_assigns [:perex] .nil? – Hannes 2013-06-03 16:12:57

12

Per mislav的回答是,我在Rails API中寻找该文档,并在Class ActionView::Base(标题为“将局部变量传递给子模板”标题下)中找到该文档。然而,这并不值得搜索,因为它几乎没有比mislav更多的话。但它建议使用此模式:

if local_assigns.has_key? :perex 
6

考虑到considerationg mislav's original answerKenB's elaboration,我认为以下是绝对的最佳方法(虽然我开到的意见)。如果密钥不存在于原始散列中,它将利用Ruby的Hash#fetch方法备用替代值。

perex = local_assigns.fetch(:perex, true) 

这比||=方法,大多数用户会建议,因为有时你会希望允许false值甚至更好。例如,下面的代码将从未允许false值在传递:

perex = local_assigns[:perex] || true 
相关问题