【问题标题】: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 - 我同意。谢谢。

标签: ruby operators


【解决方案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

    【讨论】:

      猜你喜欢
      • 2017-06-28
      • 2014-07-15
      • 1970-01-01
      • 2012-06-04
      • 2011-03-22
      • 2011-09-16
      • 2022-01-07
      • 2012-08-23
      相关资源
      最近更新 更多