Get has_many from ActiveRecord::Relaiton

125 views Asked by At

Is it possible to get the has_many records from an ActiveRecord::Relation?

i.e. Book.where(fiction: true).pages as opposed to Book.where(fiction: true).collect { |book| book.pages }

Ideally I'd like to be able to get all the records using one ActiveRecord query, so I don't have to build up the array in memory, and make the code a little cleaner, especially when the relationship has multiple levels (i.e. Book.where(fiction: true).pages.words

2

There are 2 answers

4
Arup Rakshit On BEST ANSWER

Well the below,

Book.where(fiction: true).collect { |book| book.pages }

can be written as :

Page.joins(:book).where("books.fiction = ?", true)

Similar way :

Word.joins(page: :book).where("books.fiction = ?", true)
0
aratak On

You may create separate has_many relation between parent object (lets say that it's Library) and pages with option through.

class Page
  belongs_to :book
end

class Book
  belongs_to :library
  has_many :pages
end

class Library
  has_many :books
  has_many :pages, through: :books
  has_many :fiction_books, -> { where(fiction: true) }, class_name: 'Book', foreign_key: 'library_id'
  has_many :fiction_pages, through: :fiction_books, source: :pages
end

Library.first.fiction_pages

I would notice that parent object will help you to build right architecture with too complicated logic, so instead of Book.where(fiction: true).pages you will write just current_library.fiction_pages

If the logic of application doesn't require such parent object, you may fake it via separate helper which can be placed in ApplicationController:

class ApplicationController
  helper_method :current_library

  protected

  def current_library
    @current_library ||= Library.first
  end

end

In this case all AR objects should be fetched via the library method or via the childs of library.