28

我有一个在 ERB 之上编写的非常古老的模板系统。它依赖于存储在数据库中的 ERB 模板。那些被读取和渲染。当我想将数据从一个模板传递到另一个模板时,我使用 Rails 渲染方法的 :locals 参数。为了在某​​些模板中设置这些变量的默认变量,我使用定义的?方法简单地告诉我是否已经定义了局部变量,如果没有,我用默认值初始化它,如下所示:

unless defined?(perex)
  perex = true
end

我正在将应用程序升级到最新的 Rails,我看到一些奇怪的行为。基本上这有时有效(有时 perex 未定义),有时则无效(perex 已定义并设置为 nil)。这发生在没有任何其他改变的情况下。

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

编辑:实际问题是由似乎是 Ruby/eRB 错误引起的。有时,除非语句会起作用,但有时不会。奇怪的是,即使第二行被执行,perex仍然对世界其他地方保持零。删除定义?解决了这个问题。

4

4 回答 4

39

第一:实际上,defined?是一个运算符

第二:如果我正确理解了您的问题,那么使用这个 Ruby 习语的方法是:

perex ||= true

如果它是未定义perex的或nil. 这不完全是您的示例所做的,因为您的示例不会在值为 时评估分配nil,但是如果您依赖它,那么在我看来,如果没有看到它,您就没有编写清晰的代码。

编辑:正如 Honza 所说,上面的语句将替换perexwhen it's的值false。然后我提出以下重写最小行数:

perex ||= perex.nil?  # Assign true only when perex is undefined or nil
于 2008-10-26T22:26:50.793 回答
25

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

local_assigns[:perex]

defined?这与由于实现限制而无法使用的解释一起记录在 Rails API 中。

于 2009-03-11T09:59:34.183 回答
12

根据 mislav 的回答,我在 Rails API 中查找该文档,并在Class ActionView::Base中找到它(在“将局部变量传递给子模板”标题下)。然而,这几乎不值得搜索,因为它几乎没有比米斯拉夫多说什么。除了它推荐这种模式:

if local_assigns.has_key? :perex
于 2009-12-17T20:00:23.917 回答
6

考虑到g mislav 的原始答案KenB 的阐述,我认为以下是绝对最好的方法(尽管我持开放态度)。如果原始哈希中不存在键,它会利用 Ruby 的Hash#fetch方法回退到备用值。

perex = local_assigns.fetch(:perex, true)

这甚至比||=大多数用户建议的方法更好,因为有时您会想要允许false值。例如,以下代码将永远不允许false传入值:

perex = local_assigns[:perex] || true
于 2012-07-23T16:42:11.823 回答