Самый чистый способ запроса полиморфной ассоциации? - PullRequest
0 голосов
/ 13 декабря 2018

Проблема: У меня есть рабочее решение, но есть подозрение, что это, вероятно, довольно сложный расчет.Хотелось бы услышать более эффективные способы достижения этого.

Цель: Я хочу получить список книг , упорядоченный по приоритету, где книга - ЛИБОполиморфно связаны с школой или классом .

  • Школы: много классов по темам
  • Классы: одна школа по темам
  • Книги: можно забронировать в классах или школах

Текущий файл представления класса:

<%  @school_class_books.order("priority ASC").each do |book| %>
    <b><a href="<%= book.url %>"><%= book.name %></a></b><br />
    <%= book.long %><br /><br />
<% end %>

Текущий контроллер class.rb:

@school_class_books = Book.all.where(bookable_type: ["School","Class"],
 bookable_id: [@class.school.id,@class.id])

1 Ответ

0 голосов
/ 13 декабря 2018

Прежде чем рассматривать какие-либо проблемы с производительностью, вы должны знать, что написанный вами код вызовет ошибки, найдя Книги, которые не должны быть найдены.

Например, если @school.id = 10 и @class.id = 15, этот запрос вернет книгу с полями, в которых можно забронировать: bookable_id = 15 и bookable_type = "Школа".

Эта книга принадлежит другой школе!

Это может быть проще сделать:

@books = Book.where(bookable: @school).to_a.concat(Book.where(bookable: @class).to_a)

Это полиморфный синтаксический сахар для:

@books = Book.where(bookable_type: @school.class.to_s, bookable_id: @school.id).to_a.concat(Book.where(bookable_type: @class.class.to_s, bookable_id: @class.id).to_a)

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

Что касается производительности, использование синтаксиса, такого как where(my_attribute: [value1, value2, value3]), приведет к SQL, подобному WHERE books.my_attribute IN (value1, value2, value3).

Операторы SQL, использующие IN, могут быть неэффективными, поскольку они затрудняют использование сервером базы данных индексов в поле my_attribute (в данном случае bookable_id).

Наконец, вам следует рассмотреть возможность переименования модели Class в Course, чтобы избежать коллизий пространства имен с ключевым словом Ruby class или путаницы программиста при чтении имен переменных.Рассмотрим неловкость bookable_type: @class.class.to_s

...