我们啥时候在 Rails 中使用 "||=" 运算符?它的意义是啥? [复制]

Posted

技术标签:

【中文标题】我们啥时候在 Rails 中使用 "||=" 运算符?它的意义是啥? [复制]【英文标题】:When do we use the "||=" operator in Rails ? What is its significance? [duplicate]我们什么时候在 Rails 中使用 "||=" 运算符?它的意义是什么? [复制] 【发布时间】:2011-08-07 04:14:57 【问题描述】:

可能重复:What does the operator ||= stands for in ruby?

我对 Rails 中 ||= 运算符的使用感到困惑。我在网上找不到任何有用的东西。谁能指导一下?

如果有任何您知道的网络链接,请告诉我。

我想知道以下语句的含义:

@_current_user ||= session[:current_user_id] &&
      User.find(session[:current_user_id])

【问题讨论】:

这不是“Rails”,而是标准的 Ruby 运算符。 @the Tin Man - 我同意。谢谢。 【参考方案1】:

首先在 C 中流行,二元运算符的简写,例如:

a += b      # and...
a ||= b

表现得像:

a = a + b   # and ... note the short circuit difference ... 
a || a = b

重新安排更有效的短路是处理 nil 检查的一种优雅方式,因为它可以完全避免分配。分配可能有副作用。这只是 Ruby 中经过深思熟虑的设计的另一个例子。

请参阅http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html 以获得更冗长的解释。

【讨论】:

-1。这个答案实际上并不正确。 a ||= b 不等于 a = a || b。请参阅rubyinside.com/… 甚至接受的答案。这是一个普遍的误解。接受的答案实际上是正确的答案。 a ||= b 等价于a || a = b,即如果a 不是falsyfalsenil),则将a 设置为b 的值。跨度> ^^^ Muphry's law 的经典案例。我的意思是:如果a 是假的falsenil),那么将a 设置为b 的值。 很好,我现在了解了Muphry's Law, 呵呵。答案固定。【参考方案2】:

如果您有 C# 经验,我相信它与 C# 中的 null-coalescing (??) 运算符类似(但更多的是 Ruby 技巧)

int? y = x ?? -1

如果 x 不为 null,则将 x 分配给 y,否则使用“默认”值 -1。

同样,||= 被称为 T 方运算符,我相信。

a || = b

a || a = b

发表你的声明

@_current_user ||= session[:current_user_id] &&
    User.find(session[:current_user_id])

基本上,它会查看 @_current_user 是否为 nil。如果它有一些价值,不要管它(当前用户。)否则,使用用户 ID 从会话中获取当前用户。它首先查看 id 是否在会话中,然后从用户那里获取。

有关“T-square”运算符的更多信息,请查看以下博客:

http://blogs.oracle.com/prashant/entry/the_ruby_t_square_operator

【讨论】:

【参考方案3】:

让我们分解一下:

@_current_user ||= SOMETHING

这就是说,如果 nilfalse 或未定义,请将 @_current_user 设置为 SOMETHING。否则将其设置为@_current_user,或者换句话说,什么也不做。扩展形式:

@_current_user || @_current_user = SOMETHING

好的,现在到右侧。

session[:current_user_id] &&
      User.find(session[:current_user_id])

您通常会看到 && 仅具有布尔值,但在 Ruby 中您不必这样做。这里的技巧是,如果session[:current_user_id] 不为零,并且User.find(session[:current_user_id]) 不为零,则表达式将计算为User.find(session[:current_user_id]),否则为nil。

所以把它们放在伪代码中:

if defined? @_current_user && @_current_user
  @_current_user = @_current_user
else
  if session[:current_user_id] && User.find(session[:current_user_id])
    @_current_user = User.find(session[:current_user_id])
  else
    @_current_user = nil
  end
end

【讨论】:

谢谢迈克。这样就很清楚了。 很高兴我能帮助@mad.geek。祝你好运 :) 请记住,如果您觉得这似乎正确回答了您的问题,请确保将其标记为正确。 学究起来,a ||= b其实就相当于a || a = b 如果您使用布尔值作为变量的数据类型,请注意不要将其放入 rails after_initialize 方法。因为如果您尝试在 after_initialize 中使用变量 ||= true 将默认值设置为 true,它将几乎总是将变量设置为 true。我这样做并浪费了 2 天时间来查找错误,因为我认为只有当 nil 是对象进入 after_initialize 时变量具有的值时,它才会将值设置为 true。 @ReinHenrichs 不是a = a || b吗?【参考方案4】:

这是缓存能力。

a ||= 1  # a assign to 1
a ||= 50 # a is already assigned, a will not be assigned again

puts a
#=> 1

这在你从数据库加载当前用户时很有用,如果这是之前加载的,语句将不会尝试评估等式的正确部分,即 DRY,因此你可以将其视为缓存运算符。

参考: http://railscasts.com/episodes/1-caching-with-instance-variables

【讨论】:

以上是关于我们啥时候在 Rails 中使用 "||=" 运算符?它的意义是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Rails:“渲染模板”实际上意味着啥

我们啥时候应该在 Xcode 中使用“嵌入式二进制文件”而不是“链接框架”?

我们啥时候在spring security中使用denyAll

Rails 啥时候编译 CoffeeScript?

“RAILS_GEM_VERSION”设置到底有啥作用?

Rails 4 中的“store_”方法有啥作用?