定义?Ruby 和 Rails 中的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/238615/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 20:45:48  来源:igfitidea点击:

defined? method in Ruby and Rails

ruby-on-railsrubycontent-management-systemerb

提问by Honza

I have a quite old templating system written on top of ERB. It relies on ERB templates stored in database. Those are read and rendered. When I want to pass data from one template to another I use the :locals parameter to Rails render method. For setting default variables of those variables in some templates I use the defined? method which simply tells me if local variable has been defined and if not I initialize it with default value like this:

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

unless defined?(perex)
  perex = true
end

I am upgrading the app to latest Rails and I see some weird behavior. Basically this sometimes works (sometimes perex is undefined) and sometimes it does not (perex is defined and set to nil). This happens without anything else changing.

我正在将应用程序升级到最新的 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?

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

Edit:The actual issue was caused by what seems to be a Ruby/eRB bug. Sometimes the unlessstatement would work, but sometimes not. The weird thing is that even if the second line got executed perexstil stayed nil to the rest of the world. Removing defined? resolved that.

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

回答by R?mulo Ceccon

First: actually, defined?is an operator.

第一:实际上,defined?是一个操作符

Second: if I understand your question correctly, the way to do it is with this Ruby idiom:

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

perex ||= true

That'll assign true to perexif it's undefined or nil. It's not exactly what your example does, since yours doesn't evaluate the assignment when the value is nil, but if you are relying on that then, in my opinion, without seeing it, you're not writing clear code.

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

Edit: As Honza noted, the statement above will replace the value of perexwhen it's false. Then I propose the following to rewrite the minimum number of lines:

编辑:作为洪扎指出,上述声明将取代的价值perex时,它的false。然后我建议如下重写最少行数:

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

回答by mislav

The safest way of testing if a local is defined in a Rails template is:

测试本地是否在 Rails 模板中定义的最安全方法是:

local_assigns[:perex]

This is documented in the Rails API together with the explanation that defined?cannot be used because of a implementation restriction.

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

回答by KenB

Per mislav's answer, I went looking for that documentation in the Rails API, and found it in Class ActionView::Base(under the heading "Passing local variables to sub templates"). It was hardly worth the search, though, since it barely said anything more than mislav did. Except that it recommends this pattern:

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

if local_assigns.has_key? :perex

回答by Matt Huggins

Taking into considerationg mislav's original answerand KenB's elaboration, I think the following is the absolute best approach (though I'm open to opinion). It utilizes Ruby's Hash#fetchmethod to fallback on an alternate value if the key does not exist in the original hash.

考虑到mislav 的原始答案KenB 的阐述,我认为以下绝对是最好的方法(尽管我愿意接受意见)。如果键不存在于原始散列中,它利用 Ruby 的Hash#fetch方法回退到备用值。

perex = local_assigns.fetch(:perex, true)

This is even better than the ||=method that most users will suggest since sometimes you will want to allow falsevalues. For example, the following code will neverallow a falsevalue to be passed in:

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

perex = local_assigns[:perex] || true