English 中文(简体)
在 Ruby 和 Rails 中定义的方法?
原标题:
  • 时间:2008-10-26 21:03:22
  •  标签:

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

unless defined?(perex)
  perex = true
end

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

I have two questions: Is there any better way other than using defined? which is proving unreliable (was reliable for several years on top Rails 1.6)? Such a way should not result in me rewriting all the templates. I have been going through Ruby docs and was not able to find anything about defined? method. Was it deprecated or am I just plain blind?

编辑:实际问题可能是由于Ruby/eRB错误引起的。有时候unless语句会起作用,但有时候不会。奇怪的是,即使第二行被执行了,perex仍然对世界其余部分为空。删除defined?解决了这个问题。

最佳回答

首先,defined?是一个运算符

第二:如果我理解您的问题正确,实现的方法是使用 Ruby 语言中的这个惯用法:

perex ||= true

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

编辑:正如Honza所指出的,上述语句将在false时替换perex的值。因此,我建议采用以下方式来重写最少行数:

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 中找到了它(在"向子模板传递本地变量"标题下)。虽然这几乎没有什么值得寻找的,但它几乎没有说比Mislav更多的内容。除了它推荐这种模式:

if local_assigns.has_key? :perex

考虑到 mislav 原始答案KenB 的详细解释,我认为以下是最佳方法(尽管我愿意听取意见)。它利用了 Ruby 的 Hash#fetch 方法,以备选值替代原始哈希中不存在的键值。

perex = local_assigns.fetch(:perex, true)

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

perex = local_assigns[:perex] || true




相关问题
热门标签