查询多态关联的最简洁方法?
Cleanest way to query polymorphic association?
问题: 我有一个可行的解决方案,但我暗暗怀疑它可能计算量很大。很想听听任何更有效的方法来实现这一目标。
目标: 我想提取 书籍 的列表,按优先级排序,其中书籍与 [= 多态关联20=]学校或class.
- 学校:有很多 classes,通过主题
- 类:拥有一所学校,通过话题
- 书籍:可由 classes 或学校
预订
当前 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])
在考虑任何性能问题之前,您应该知道您编写的代码会通过查找不应找到的书籍而导致错误。
例如,如果 @school.id
= 10 且 @class.id
= 15,此查询将 return 一本可预订字段设置为:bookable_id
= 15 且bookable_type
= "School"。
那本书属于不同的学校!
做起来可能更简单:
@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
的尴尬
问题: 我有一个可行的解决方案,但我暗暗怀疑它可能计算量很大。很想听听任何更有效的方法来实现这一目标。
目标: 我想提取 书籍 的列表,按优先级排序,其中书籍与 [= 多态关联20=]学校或class.
- 学校:有很多 classes,通过主题
- 类:拥有一所学校,通过话题
- 书籍:可由 classes 或学校 预订
当前 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])
在考虑任何性能问题之前,您应该知道您编写的代码会通过查找不应找到的书籍而导致错误。
例如,如果 @school.id
= 10 且 @class.id
= 15,此查询将 return 一本可预订字段设置为:bookable_id
= 15 且bookable_type
= "School"。
那本书属于不同的学校!
做起来可能更简单:
@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。
SQL 语句可能效率低下,因为它们使数据库服务器更难在 my_attribute
字段(在本例中为 bookable_id
)上使用索引。
最后,您应该考虑将您的 Class
模型重命名为 Course
以避免名称空间与 Ruby 的 class
关键字发生冲突,或者在读取变量名称时避免程序员混淆.考虑 bookable_type: @class.class.to_s