查询多态关联的最干净方法?

时间:2018-12-12 22:13:43

标签: ruby-on-rails polymorphic-associations

问题:我有一个可行的解决方案,但有一个偷偷的怀疑,即它可能在计算上很繁琐。很想听听实现这一目标的任何更有效的方法。

目标:我想按优先级提取的列表,其中该书与 school 或< em> class 。

  • 学校:通过主题有很多课程
  • 课程:通过主题学习一所学校
  • 书籍:可按班级或学校预订

当前类视图文件:

<%  @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 :(得分:1)

在考虑任何性能问题之前,您应该知道所写的代码将通过查找不应找到的书本而导致错误。

例如,如果@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])的语法会产生类似WHERE books.my_attribute IN (value1, value2, value3)的SQL。

使用IN的SQL语句效率不高,因为它们使数据库服务器更难使用my_attribute字段(在本例中为bookable_id)上的索引。

最后,您应该考虑将Class模型重命名为Course,以避免名称空间与Ruby的class关键字冲突,否则程序员在读取变量名时会感到困惑。考虑一下bookable_type: @class.class.to_s

的尴尬