为什么单个 `=` 在 `if` 语句中起作用?
Why does single `=` work in `if` statement?
此代码作为与 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 "intelliJ IDEA" 同意我的担忧。
在Ruby中,一个等号用于赋值。表达式
data = session["devise.facebook_data"]
将计算 session["devise.facebook_data"]
的结果分配给名为 data
.
的局部变量
如果 session
哈希没有 "devise.facebook_data"
键,它将 return nil
并且 data
将被分配 nil
.赋值计算为被赋值的值,因此赋值也将计算为 nil
。 nil
在布尔上下文中被认为是错误的,因此不会评估 &&
的右操作数。这样,您就不会得到 NoMethodError
试图调用 nil["extra"]["raw_info"]
.
如果 session
散列 确实 有一个 "devise.facebook_data"
键,data
将被设置为与之关联的值。 nil
和 false
以外的任何值都被认为是真实的,因此将评估 &&
运算符的右侧操作数。
如果条件为真,将评估 then
子句,它使用条件中分配的 data
变量。
注意:我相信也可以在 &&
运算符的右侧使用 data
变量,即条件可以这样读:
if data = session["devise.facebook_data"] && data["extra"]["raw_info"]
但我必须检查一下。
赋值运算符 (=
) returns 赋值,然后由 if
求值。在ruby中,只有false
和nil
被认为是false
。在布尔上下文中,其他所有内容的计算结果为 true
(如 if
)。
Ruby 不关心条件中的类型,不像 Java。只要该值既不是 nil 也不是 false,它就会通过。
在您的示例中,您实际上歧视了 nil:if 条件确保数据确实存在并且不是 nil,因此我们可以使用它,假设它是一个散列。这是 Ruby.
中的常见模式
if
语句有效的唯一必要条件是布尔表达式。在这种情况下,由于 =
returns 赋值的结果,实际测试的是 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
此代码作为与 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 "intelliJ IDEA" 同意我的担忧。
在Ruby中,一个等号用于赋值。表达式
data = session["devise.facebook_data"]
将计算 session["devise.facebook_data"]
的结果分配给名为 data
.
如果 session
哈希没有 "devise.facebook_data"
键,它将 return nil
并且 data
将被分配 nil
.赋值计算为被赋值的值,因此赋值也将计算为 nil
。 nil
在布尔上下文中被认为是错误的,因此不会评估 &&
的右操作数。这样,您就不会得到 NoMethodError
试图调用 nil["extra"]["raw_info"]
.
如果 session
散列 确实 有一个 "devise.facebook_data"
键,data
将被设置为与之关联的值。 nil
和 false
以外的任何值都被认为是真实的,因此将评估 &&
运算符的右侧操作数。
如果条件为真,将评估 then
子句,它使用条件中分配的 data
变量。
注意:我相信也可以在 &&
运算符的右侧使用 data
变量,即条件可以这样读:
if data = session["devise.facebook_data"] && data["extra"]["raw_info"]
但我必须检查一下。
赋值运算符 (=
) returns 赋值,然后由 if
求值。在ruby中,只有false
和nil
被认为是false
。在布尔上下文中,其他所有内容的计算结果为 true
(如 if
)。
Ruby 不关心条件中的类型,不像 Java。只要该值既不是 nil 也不是 false,它就会通过。
在您的示例中,您实际上歧视了 nil:if 条件确保数据确实存在并且不是 nil,因此我们可以使用它,假设它是一个散列。这是 Ruby.
中的常见模式if
语句有效的唯一必要条件是布尔表达式。在这种情况下,由于 =
returns 赋值的结果,实际测试的是 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