【问题标题】:Rails 5 ActiveRecord - check if any results before using methodsRails 5 ActiveRecord - 在使用方法之前检查是否有任何结果
【发布时间】:2017-01-13 21:35:51
【问题描述】:

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

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

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

但如果不存在具有此名称的用户,我会收到错误消息:

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

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

我可以考虑使用 if 子句的各种方法:

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

if user
user_email = user.email
end

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

【问题讨论】:

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


    【解决方案1】:

    您可以使用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

    【讨论】:

    • 如果你的 Ruby 没有 &.,Rails 中也有 tryUser.where(name: name).first.try(:name)。但是try 也会吞下不是来自nil 的NoMethodErrors,所以有时你会想要try!
    【解决方案2】:

    我经常使用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. 
    

    【讨论】:

      【解决方案3】:

      你总是可以使用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
      

      除非您真的认为您只会使用一次用户记录,否则您应该更喜欢明确说明您正在使用的任何逻辑。

      【讨论】:

        猜你喜欢
        • 2018-09-15
        • 1970-01-01
        • 1970-01-01
        • 2011-02-21
        • 2011-05-16
        • 1970-01-01
        • 2010-10-26
        • 1970-01-01
        相关资源
        最近更新 更多