使用单个 ActiveRecord 对象向 ActiveRecord::Relation 对象添加记录

3
我需要将单个ActiveRecord对象附加到已加载的ActiveRecord :: Relation中。

E.g:

class BooksController < ApplicationController
  def index
    @books = Book.where(author: User.find(params[:user_id]))
    @books << Book.find_by_name("One More Book")
  end
end

如上所示,我尝试使用ActiveRecord的<<方法,但它返回错误:
NoMethodError: undefined method `<<' for #<Book::ActiveRecord_Relation:0x007f9fbdc6db80>

有没有一种优雅的方法来做这件事?

谢谢!


1
为什么不在一个查询中使用“or”? - fanta
3个回答

3

作为一种临时解决方案,我已经采取了以下措施:

books = Book.where(author: User.find(params[:user_id])).pluck(:id)
books << Book.find_by_name("One More Book").id
@books = Book.where(id: books)

出于显而易见的原因,这种解决方案远非理想,但在找到更好的解决方案之前,它确实有效。


2
您可以使用Rails 5中介绍的or方法,但这仅适用于where(返回ActiveRecord :: Relation对象)而不适用于find_by_name(因为它返回一个Book对象)。
Book.where(author_id: params[:user_id])).or(Book.where(name: "One More Book"))

如果关系定义良好,这也应该有效:
Book.where(author: params[:user_id])).or(Book.where(name: "One More Book"))

请注意,where可能会返回多个对象。在or中使用where+limit也是不允许的。
如果您想追加单个对象,可以通过提取id来实现,但这会导致3个查询而不是1个:
users_array = User.where(author: params[:user_id]) | [Book.find_by_name("One More Book")]
Book.where(id: users_array)

或者,根据您之后的操作,将结果放在一个数组中可能足够:

Book.where(author_id: params[:user_id])) | [Book.find_by_name("One More Book")]

请注意使用 |(联合),因为我假设您不想要重复项。否则,您可以使用 +,但这仅对数组有所不同,而对于 ActiveRecord::Relation(没有重复项)没有影响。

0

由于这是Rails 5,您可以使用or方法

Books.where(author: User.find(params[:user_id])).or.where(name: "One More Book")

谢谢您的回复。看起来不错,但是我收到了错误信息:ArgumentError: Relation passed to #or must be structurally compatible. Incompatible values: [:joins]。有什么想法吗?再次感谢! - simonlehmann
书籍和作者之间的模型关联是什么?书籍是否有一个外键 author_id? - Michael Gorman
这似乎是一个已经修复的错误:https://github.com/rails/rails/issues/24055 - Ana María Martínez Gómez
但是您不需要额外查询来查找作者,我已经发布了这个答案的改进版本 :) - Ana María Martínez Gómez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接