TypeError:没有隐式将nil转换为带有gsub的字符串
我想循环遍历系统中的所有用户,并使用电子邮件地址减去@和@之后的所有内容更新用户名。 如果电子邮件是零或空字符串,然后我就分配unknown_user与当前迭代指数:TypeError:没有隐式将nil转换为带有gsub的字符串
User.all.each do |user|
puts user.email
username = (user.email.present?? user.email.gsub(/(.+)@.+/,$1) : "unknown_user#{i}")
puts username
end
它失败:
crodriguez
TypeError: no implicit conversion of nil into String
from (irb):45:in `gsub'
from (irb):45:in `block in irb_binding'
我不知道在哪里的零值。如果电子邮件不存在,那么gsub永远不会被调用。我在这里错过了什么?
零值不是你的user.email
。 gsub
方法需要一个字符串作为它的第二个参数,它将替换为匹配。正如mu指出的那样,当参数传递给gsub
时,$1
全局变量还不可用。
假设你想只用电子邮件的名称部分,你甚至不需要一个正则表达式:
username, _ = user.email&.split('@')
在此,username
将nil
时user.email
为nil
,并@
前的字符串除此以外。
如果你想设置username
到默认的字符串,如你的例子:
User.find_each do |user|
username = user.email.split('@').first if user.email.present?
username ||= "unknown_user_#{user.id}"
# do something with `username`
end
我免掉这里的三元,因为它不是适合于阅读和理解的代码,未来改变并不容易。如果需要,您可以重构使用它。
user.email.gsub(/(.+)@.+/) { $1 }
当你说:
更紧凑的选项:'username = user.email.to_s.split('@')。 “unknown_user _#{user.id}”' – Thilo
@Thilo当'user.email'为零时,你会得到一个NoMethodError。 ;) – coreyward
@coreyward'nil.to_s#=>“”':)。现在真正的问题是,他没有看到他正在验证电子邮件地址,它可能根本不包含@。 – engineersmnky
编号的全局变量($1
,$2
,...)当您使用的String#gsub
块形式,所以你可以说是唯一可用的
user.email.gsub(/(.+)@.+/, $1)
$1
全局评估当gsub
参数列表正在构建(即在gsub
可以分配它的值之前),所以你不应该期望$1
有什么有用的价值。
这就是说,我可能会去coreyward's approach,而不是打扰一个正则表达式。
请注意,这实际上并没有更新任何它只是简单地分配一个局部变量。如果你已经知道,我很抱歉。此外,它不会出现你正在验证的电子邮件地址为“crodriguez”不是一个有效的电子邮件 – engineersmnky
FYI:要在gsub替换模式中使用反向引用,只需使用''\ 1'':'gsub(/(.+) @。+ /,'\ 1')' –