【问题标题】:Rails: Why does find(id) raise an exception in rails? [duplicate]Rails:为什么 find(id) 会在 rails 中引发异常? [复制]
【发布时间】:2023-04-07 16:07:01
【问题描述】:

可能重复:
Model.find(1) gives ActiveRecord error when id 1 does not exist

如果数据库中没有 id 为 1 的用户,尝试User.find(1) 将引发异常。

这是为什么?

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    因为这是架构师希望 find(id) 工作的方式,如 RDoc 中所示:

    按 id 查找 - 这可以是特定 id (1)、id 列表 (1, 5, 6) 或 id 数组 ([5, 6, 10])。如果没有找到所有列出的 id 的记录,则会引发 RecordNotFound。

    如果您不希望引发异常,请使用 find_by_id,如果找不到具有指定 id 的对象,它将返回 nil。您的示例将是 User.find_by_id(1)

    【讨论】:

    • RecordNotFound 被提出,不返回。这允许调用者的控制流不同,因为您不必检查返回值是否为 nil(您将使用 begin/rescue 块代替)。
    • 这仍然不能解释为什么它是默认行为,在 ActiveRecord 的大多数其他部分中,默认行为是返回 nil 或 false 失败,并将异常控制流留给以结尾的方法一声巨响(#save!)。
    • 我认为引发错误的原因是基本控制器可以捕获它并显示 404 页面。如果你点击 /widgets/2 并且没有 id==2 的小部件,那么你会得到一个 404,这是 IMO 有意义的。
    • @Nick find_by_id(1) 确实已被弃用。但你可以使用find_by(id: 1)
    • 关于如何避免异常的解释很有用,但这里没有真正回答为什么会这样的问题。换句话说,“因为制作它的人想要那样”不是一个有用的答案,“文档说它就是那样”也不是一个有用的答案。
    【解决方案2】:

    在 runako 的解释中,选择是否引发异常实际上非常有用。我正在开发一个博客应用程序,我想添加对查看下一个或上一个博客条目的支持。我能够向我的 Post 模型添加两个实例方法,当您在查看第一篇文章时尝试获取上一篇文章或查看最后一篇文章时尝试获取下一篇文章时,它们只会返回 nil

    def next
      Post.find_by_id(id + 1)
    end
    
    def previous
      Post.find_by_id(id - 1)
    end
    

    这避免了有条件地生成上一篇文章/下一篇文章链接的帮助程序代码必须处理 RecordNotFound 异常,这会很糟糕,因为它将使用异常进行控制流。

    【讨论】:

    • 如果您的数据库中的记录没有顺序 ID,这不是很脆弱吗?
    • @zoltarSpeaks 会的,但实际上它们确实有连续的 ID,所以这完全不是问题。
    • 例如,如果您有一个排除项,您将遇到一个难以跟踪的零星错误。实现下一个/上一个的更好方法是: Post.where("id > ?", id).limit(1) for next 和 Post.where("id
    • 如果Post 从数据库中删除?
    • 所描述的用例可能很糟糕(请参阅其他 cmets),但本质上“选择是否引发异常实际上非常有用”是完全正确的,恕我直言!
    猜你喜欢
    • 2016-12-29
    • 2020-03-13
    • 1970-01-01
    • 2012-08-22
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多