Rails 5 ActiveRecord - 在使用方法

时间:2017-01-13 21:35:51

标签: ruby-on-rails postgresql activerecord rails-activerecord

在我的Rails 5 + Postgres应用程序中,我进行了如下查询:

user = User.where("name = ?", name).first.email

所以这给了我第一个用户名的电子邮件。

但是如果没有这个名字的用户存在,我会收到一个错误:

  

NoMethodError(未定义的方法`email'代表nil:NilClass)

在使用该方法之前,如何检查我是否有任何结果?

我可以考虑使用if-clauses进行各种方式:

user = User.where("name = ?", name).first

if user
user_email = user.email
end

但这似乎不是最优雅的方式,我相信Rails有更好的方法。

3 个答案:

答案 0 :(得分:2)

您可以使用find_by,如果找不到任何内容,则返回对象或nil

user = User.find_by(name: name)
if user
  ...
end

话虽如此,如果你期望有多个元素,你仍然可以使用where子句。

users = User.where(name: name)
if users.any?
  user = users.first
  ...
end

然后还有Ruby 2.3的另一种方法,你可以做到

User.where(name: name).first&.name

如果您不确定对象是否为&,则可以使用nil,在这种情况下,如果找不到用户,整个语句将返回nil。< / p>

答案 1 :(得分:1)

我经常使用try来处理这种情况。

user = User.where("name = ?", name).first.try(:email)

它将返回电子邮件,或者如果集合为空(并且first为nil),它将返回nil而不会引发错误。

如果找到记录但没有方法或属性存在,那么它也不会失败,所以你不太可能发现错字,但希望你的测试能够覆盖它。

user = User.where("name = ?", name).first.try(:emial)   

如果您使用Ruby 2.3 &.功能,这不是问题,因为它只适用于nil对象......

user = User.where("name = ?", name).first&.emial
# this will raise an error if the record is found but there's no emial attrib. 

答案 2 :(得分:-1)

您可以随时使用User.where("name = ?", name).first&.email,但我不同意

user = User.where("name = ?", name).first

if user
  user_email = user.email
end

特别不优雅。你可以用

之类的东西来清理它
def my_method
  if user
    # do something with user.email
  end
end

private

def user
  @user ||= User.where("name = ?", name).first
  # @user ||= User.find_by("name = ?", name) # can also be used here, and it preferred.
end

除非你真的认为你只会使用一次用户记录,否则你应该更倾向于使用你正在使用的任何逻辑。