if语句的逻辑出了点问题

时间:2014-05-30 17:32:44

标签: ruby

我有一种方法可以检查用户是否填写了他的个人资料信息:

def checkUser
  if (current_user.fullname.nil? && current_user.availability.nil? && current_user.rate.nil? && current_user.terms.nil? && current_user.location_city.nil? && current_user.location_state.nil? && current_user.location_country.nil? && current_user.biography.nil?)
    return true
  else
    return false
  end
end

当我尝试时似乎出了问题。属性的值为空(nil),fullname属性不为空。

我正在调试并发现current_user.rate.nil?正在返回truecurrent_user.rate.nil?正在返回false这是正常的。但是,通过使用Rails.logger.info,我发现checkUser方法返回true而不是false

我不确定我用于返回true或false的方式是否合适。 if条件中的返回true或false是否表示checkUser方法的返回值?

4 个答案:

答案 0 :(得分:2)

空字符串与nil不同。如果用户没有输入任何内容,则可能只是空字符串,这不是零。

"".nil?
"".empty?

此外,如果所有内容都为nil,则您的方法仅返回true。这似乎不是正确的逻辑。我假设如果没有填写任何字段,你希望它返回true吗?

答案 1 :(得分:1)

默想:

def checkUser
  if (current_user.fullname.nil? && current_user.availability.nil? && current_user.rate.nil? && current_user.terms.nil? && current_user.location_city.nil? && current_user.location_state.nil? && current_user.location_country.nil? && current_user.biography.nil?)
    return true
  else
    return false
  end
end

可写成:

def valid?
  current_user.fullname.nil? && 
  current_user.availability.nil? && 
  current_user.rate.nil? && 
  current_user.terms.nil? && 
  current_user.location_city.nil? && 
  current_user.location_state.nil? && 
  current_user.location_country.nil? && 
  current_user.biography.nil?
end

可以简化为:

def valid?
  [
    current_user.fullname, 
    current_user.availability, 
    current_user.rate, 
    current_user.terms, 
    current_user.location_city, 
    current_user.location_state, 
    current_user.location_country, 
    current_user.biography
  ].all?{ |v| v.nil? }
end

但这甚至可以简化为:

def valid?
  [
    :fullname, 
    :availability, 
    :rate, 
    :terms, 
    :location_city, 
    :location_state, 
    :location_country, 
    :biography
  ].all?{ |m| current_user.send(m).nil? }
end

需要考虑的事项:

  • Ruby会自动返回方法中看到的最后一个值。这意味着如果比较已经返回true或false值,则不必说return truereturn false。事实上,如果不需要显式return some_value,那么它被认为是不好的Ruby风格,因为它浪费了打字,空间和必要的脑能量来阅读。
  • Ruby中的方法名称是用snake_case编写的,而不是用camelCase编写的。它似乎是____ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ <
  • 方法名称在动词或提问时读得更好。 “check_user”没问题,但是调用这样的方法“有效”是更惯用的吗?还是“is_ok?”因为你想要一个布尔真/假响应。

答案 2 :(得分:1)

这里有很大的改进空间。

首先,抛弃return关键字,因为它只是短路方法的必要条件。 E.g。

def age_category
  return "unknown" if age.nil?

  if age < 0
    "unborn"
  elsif age < 18
    "child"
  elsif age < 65
    "adult"
  elsif age < 120
    "senior"
  else
    "ancient"
  end  
end

由于if / else条件是方法的最后一部分,条件的输出将是方法的返回值。

考虑到这一点,我们可以改写:

def checkUser
  if (current_user.fullname.nil? && current_user.availability.nil? && current_user.rate.nil? && current_user.terms.nil? && current_user.location_city.nil? && current_user.location_state.nil? && current_user.location_country.nil? && current_user.biography.nil?)
    true
  else
    false
  end
end

但是,检查的条件本身返回一个布尔值,因此不需要if / else。只需评估括号。

def checkUser
  (current_user.fullname.nil? && current_user.availability.nil? && current_user.rate.nil? && current_user.terms.nil? && current_user.location_city.nil? && current_user.location_state.nil? && current_user.location_country.nil? && current_user.biography.nil?)
end

但是,所有这些代码都不是面向对象的。为什么有一个方法可以对用户对象进行严格检查以确定它是否完整?用户对象应该能够告诉你这一点,所以你可以写:

def check_user
  current_user.complete?
end

在用户类上,您可以实现以下方法

def complete?
  [fullname, availability, rate, terms, location_city, location_state, location_country, biography].none? {|attribute| attribute.to_s.empty?}
end

此方法创建一个包含所有属性的数组。然后它将它们中的每一个变成一个字符串,以检查它们是否为空。如果您的属性都不为空,则该方法返回true。

答案 3 :(得分:0)

return关键字将立即停止执行该方法并返回传递给它的任何值。在这种情况下,是真还是假。