为什么单个`=`在`if`语句中工作?

时间:2015-06-10 22:25:21

标签: ruby variable-assignment

此代码是作为与devise和OmniAuth一起使用的示例提供的,它适用于my project

class User < ActiveRecord::Base
  def self.new_with_session(params, session)
    super.tap do |user|
      if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
        user.email = data["email"] if user.email.blank?
      end
    end
  end
end

我不知道为什么它是单个等号与双等号相对应,我认为if - 陈述是必要的。我的IDE&#34; intelliJ IDEA&#34;同意我的担忧。

4 个答案:

答案 0 :(得分:7)

if语句有效的唯一必要条件是布尔表达式。在这种情况下,由于=会返回分配结果,因此实际测试的内容是session["devise.facebook_data"]的虚假。

对于像这样的代码,IntelliJ有一个很好的观点,因为如果不了解Ruby的一两件事就很难阅读。建议是将其移至明确的赋值语句中。这样做的另一个好处是可以对它进行两次干扰。

class User < ActiveRecord::Base
  def self.new_with_session(params, session)
    super.tap do |user|
      data = session["devise.facebook_data"]
      if data && data["extra"]["raw_info"]
        user.email = data["email"] if user.email.blank?
      end
    end
  end
end

答案 1 :(得分:2)

在Ruby中,单个等号用于赋值。表达式

data = session["devise.facebook_data"]

将评估session["devise.facebook_data"]的结果分配给名为data的本地变量。

如果session哈希没有"devise.facebook_data"密钥,则会返回nildata将被分配nil。分配评估为分配的值,因此分配也将评估为nilnil在布尔上下文中被认为是假的,因此不会评估&&的右操作数。这样,您就不会NoMethodError试图致电nil["extra"]["raw_info"]

如果session哈希 具有"devise.facebook_data"密钥,则data将设置为与其关联的值。除nilfalse以外的任何值都被认为是真实的,因此将评估&&运算符的右侧操作数。

如果条件是真实的,将评估then子句,该子句使用条件中指定的data变量。

注意:我相信也可以使用data运算符右侧的&&变量,即条件可以这样读取:

if data = session["devise.facebook_data"] && data["extra"]["raw_info"]

但是我必须检查一下。

答案 2 :(得分:1)

赋值运算符(=)返回指定的值,然后由if进行评估。在ruby中,只有falsenil被视为false。其他所有内容在布尔上下文中评估为true(如if)。

答案 3 :(得分:0)

与Java不同,Ruby并不关心条件中的类型。只要该值既不是零也不是假,那么它就会通过。

在您的示例中,您实际上区分了nil:if conditionnal确保数据实际存在且不是nil,因此我们可以使用它,假设它是一个哈希值。这是Ruby中常见的模式。