如何毫无例外地选择Array Rails ActiveRecord中的ID
Posted
技术标签:
【中文标题】如何毫无例外地选择Array Rails ActiveRecord中的ID【英文标题】:How to select where ID in Array Rails ActiveRecord without exception 【发布时间】:2010-11-29 07:59:02 【问题描述】:当我有一个 id 数组时,比如
ids = [2,3,5]
我表演
Comment.find(ids)
一切正常。但是当有不存在的 id 时,我得到一个异常。这通常发生在我获得与某些过滤器匹配的 ID 列表并且比我执行类似的操作时
current_user.comments.find(ids)
这一次我可能有一个有效的评论 ID,但它不属于给定的用户,所以没有找到它,我得到一个异常。
我试过find(:all, ids)
,但它会返回所有记录。
我现在唯一能做到的就是
current_user.comments.select |c| ids.include?(c.id)
但在我看来,这似乎是一种超级低效的解决方案。
有没有更好的方法来选择 数组中的 ID 而不会在不存在的记录上出现异常?
【问题讨论】:
【参考方案1】:如果只是避免您担心的异常,“find_all_by..”函数系列可以正常工作而不会引发异常。
Comment.find_all_by_id([2, 3, 5])
即使某些 id 不存在也可以使用。这适用于
user.comments.find_all_by_id(potentially_nonexistent_ids)
情况也是如此。
更新:Rails 4
Comment.where(id: [2, 3, 5])
【讨论】:
这是我的首选方案,看起来比异常处理路线更干净 作为另一个扩展,如果你需要链接复杂的条件,你甚至可以做 Comment.all(:conditions => ["approved and id in (?)", [1,2, 3]]) 这将在 Rails 4 中被弃用:edgeguides.rubyonrails.org/… @JonathanLin 是正确的,应该首选 mjnissim 的答案:***.com/a/11457025/33226 这将返回一个Array
而不是ActiveRecord::Relation
,这限制了您之后可以使用它执行的操作。 Comment.where(id: [2, 3, 5])
确实返回 ActiveRecord::Relation
。【参考方案2】:
更新:这个答案与 Rails 4.x 更相关
这样做:
current_user.comments.where(:id=>[123,"456","Michael Jackson"])
这种方法的强项在于它返回一个Relation
对象,您可以在其中加入更多.where
子句、.limit
子句等,非常有帮助。它还允许不存在的 ID 不抛出异常。
较新的 Ruby 语法是:
current_user.comments.where(id: [123, "456", "Michael Jackson"])
【讨论】:
感谢您在与数组进行比较时确认where
语法。我想我可能不得不使用IN
语句来编写 SQL,但这看起来更简洁,并且可以轻松替代已弃用的 scoped_by_id
。
这叫什么,它是如何工作的?它是 Rails 的魔法吗?!正如一位同事评论的那样,这就像“将整数与对象列表进行比较”。【参考方案3】:
如果您需要更多控制权(也许您需要说明表名),您还可以执行以下操作:
Model.joins(:another_model_table_name)
.where('another_model_table_name.id IN (?)', your_id_array)
【讨论】:
正是我想要的。谢谢! 取回对象时有什么办法可以保持your_id_array
的顺序吗?
@JoshPinter 我不认为这是期望数据库以相同顺序返回内容的可靠方法。也许在最后添加一个 ORDER BY 查询以确保事情的正确顺序。
@JonathanLin 感谢乔纳森的回复。你当然是对的。在我的情况下,使用ORDER BY
不起作用,因为订单不是基于属性的。但是,有一种方法可以通过 SQL 来完成(所以速度很快),甚至有人为它创建了一个 gem。看看这个问答:***.com/questions/801824/…【参考方案4】:
现在 .find 和 .find_by_id 方法在 rails 4 中已弃用。因此我们可以使用以下方法:
Comment.where(id: [2, 3, 5])
即使某些 id 不存在,它也会起作用。这适用于
user.comments.where(id: avoided_ids_array)
也用于排除 ID
Comment.where.not(id: [2, 3, 5])
【讨论】:
github.com/rails/activerecord-deprecated_finders .find 和 .find_by_id 方法在 rails 4 中不被弃用。【参考方案5】:为避免异常杀死您的应用,您应该捕获这些异常并按照您希望的方式处理它们,在未找到 id 的情况下为您的应用定义行为。
begin
current_user.comments.find(ids)
rescue
#do something in case of exception found
end
这里是 more info,关于 ruby 中的异常。
【讨论】:
是的,这解决了问题,但它并不是一个真正干净的解决方案 如果你要捕获一个异常,你应该声明你希望捕获的异常,否则你可能会捕获一些你没有预料到的东西并隐藏一个实际的问题。【参考方案6】:如果你想放其他条件,你也可以在named_scope中使用它
例如包括一些其他模型:
named_scope 'get_by_ids', lambda |ids| :include => [:cmets], :conditions => ["cmets.id IN (?)", ids]
【讨论】:
以上是关于如何毫无例外地选择Array Rails ActiveRecord中的ID的主要内容,如果未能解决你的问题,请参考以下文章
Rails 如何知道何时从 `sessions` 表中删除记录?