Append an ActiveRecord::Relation object with single ActiveRecord object

Viewed 2788

I need to append a single ActiveRecord object onto a loaded 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

As shown above, I have tried ActiveRecord's << method, but it returns the error:

NoMethodError: undefined method `<<' for #<Book::ActiveRecord_Relation:0x007f9fbdc6db80>

Is there an elegant way of doing this?

Thanks!

3 Answers

You can use the or method introduced in Rails 5, although this only works with where (which returns an ActiveRecord::Relation object) and not with find_by_name (as it returns a Book object).

Book.where(author_id: params[:user_id])).or(Book.where(name: "One More Book"))

If the relationship is well defined this should also work:

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

Note that where could return more than one object. Using where + limit in an or is also not allowed.

If you want to append a single object, you can do it by plucking the ids, but this raises 3 queries instead of 1:

users_array = User.where(author: params[:user_id]) | [Book.find_by_name("One More Book")]
Book.where(id: users_array)

Alternatively, depending what you are doing afterwards, having the result in an array may be enough:

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

Note the use of | (union), as I assume you don't want duplicates. Otherwise you can use +, but this only makes a different for the array and not for an ActiveRecord::Relation (there are no duplicates).

Related