新手问题 多态情况下关联表查询问题

ringokun · 2017年05月19日 · 最后由 coderliu 回复于 2017年05月24日 · 2394 次阅读

模型

class Image
    belongs_to :item, polymorphic: true
end

class Book
    has_many covers, class_name: "Image", as: :item
    enum status: {tech: 0, novel: 1}
end

现在我想查询 所属书籍的 status 为 tech 的所有图片,应该怎么写呢?

(因为还需要对结果进行分页处理,所以 select 不是很方便)


最先想的是

Image.includes(:item).where(items: {status: 0})

然而这样并不行。。。应该是多态的原因。


论坛上找到了一个解决方案:

class Image
    belongs_to :item, polymorphic: true
    belongs_to :book, foreign_key: item_id, foreigen_type: book
end
Image.includes(:book).where(books: {status: 0})

这样是可行的,我的理解是这个方法免去了多态的一环,让 Image 直接和 Book 关联起来,从而可以直接使用常规方法查询。

不过还想问一下有没有其他更好的办法

论坛里相似的问题https://ruby-china.org/topics/21537

你把不行(报错还是查询的结果不对)时候的日志发出来,这样才好诊断,另外你在排查这方面问题的时候,也是把观察日志做为重点,去看 Rails 产生的查询,是不是符合你的期望,然后通过调节 API 的用法,去凑

2 楼 已删除

先想好如果纯用 SQL 的话怎么写

4 楼 已删除

Rails 的最大危害是:让人抛弃了“祖宗”,忘了本。

本质上就是 SQL 查询,如果用 API 的方法写不出来,那就写 SQL 吧。

http://api.rubyonrails.org/v4.2.7.1/classes/ActiveRecord/QueryMethods.html#method-i-joins

API 文档中的例子已经足够说明解法了。

看看 Image.includes(:book).where(books: {status: 0}) 对应的 SQL,然后试着去理解一下。

# 如果 Book 有封面之外的 image 就不行了
Image.where(item_type: :book).joins('LEFT JOIN books ON books.id =  images.item_id').where('books.status': 0)
coderliu 回复

加上 images.item_type = 'Book' 是不是保险一些?

greatghoul 回复

因为不知道他 images.item_type 存的是什么,所以当小写的 book 写了

需要 登录 后方可回复, 如果你还没有账号请 注册新账号