ActiveRecord: возможно ли сделать соединение соединения с областью действия - PullRequest
0 голосов
/ 11 марта 2019

Вот моя оригинальная проблема.У меня есть две модели, как показано ниже.

class Author < ActiveRecord::Base
  has_many :books
end

и

class Book < ActiveRecord::Base
  belongs_to :author

  scope :available, ->{ where(available: true) }
end

Я хотел бы оставить автора в области Книги "Доступно".Ниже приведен запрос, который я хотел бы выполнить в БД.Возможно ли это сделать?

Select authors.* , count(books.*) as books_count 
From authors left outer join books on books.author_id = authors.id 
and books.available = true 
group by (authors.id) order by books_count;

Я пробовал следующий метод

 Author.joins("LEFT OUTER JOIN authors on books.author_id = authors.id")
.merge(Book.available)
.select("authors.* , count(books.*) as books_count")
.group("authors.id").order("books_count")

Но это приводит к следующему запросу.

Select authors.* , count(books.*) as books_count 
From authors left outer join books on books.author_id = authors.id 
where books.available = true 
group by (authors.id) order by books_count;

Так что удалить всеавторы, у которых нет книги.

Важно: В моей версии AR нет метода left_outer_joins

Ответы [ 2 ]

0 голосов
/ 11 марта 2019

Пока не использует вашу сферу.(в основном потому, что ваша область действия включает в себя предложение where, которое вы не хотите включать в свой запрос)

Вы можете сделать это с помощью arel, например:

book_table = Book.arel_table
author_table = Author.arel_table
author_join = author_table.join(book_table,Arel::Nodes::OuterJoin)
  .on(book_table[:author_id].eq(author_table[:id]).and(
       book_table[:available].eq(true)
    )
  )
Author.joins(author_join.join_sources)
  .select("authors.* , count(books.*) as books_count")
  .group("authors.id").order("books_count")

Это приведет кследующий SQL:

SELECT 
  authors.* , 
  count(books.*) as books_count
FROM 
  authors 
  LEFT OUTER JOIN books ON books.author_id = authors.id
    AND books.available = true
GROUP BY 
  authors.id
ORDER BY 
  books_count
0 голосов
/ 11 марта 2019

Вам нужно добавить еще один запрос, который проверит, нет ли у автора книг, тогда нам нужно будет добавить его. пожалуйста, попробуйте ниже запрос

 Author.joins("LEFT OUTER JOIN authors on books.author_id = authors.id")
.merge(Book.available)
.where("books.author_id IS NULL")
.select("authors.* , count(books.*) as books_count")
.group("authors.id").order("books_count")
...