Rails 5自定义查询问题:HABTM关联多标签产品筛选报错
嘿,我太懂新手刚接触Rails关联时踩坑的感觉了!你遇到的PG::UndefinedTable错误,核心原因有两个:一是你可能在查询里用了单数的tag表名,但Rails给Tag模型生成的数据库表是复数的tags;二是没先把products和tags表正确关联起来就直接加筛选条件,导致PostgreSQL找不到对应的表。
要筛选同时拥有Limestones和Mouldings两个标签的产品,你可以用下面这个靠谱的写法,直接放到products_controller.rb的index方法里:
@products = Product.joins(:tags) .where(tags: { name: ['Limestones', 'Mouldings'] }) .group('products.id') .having('COUNT(DISTINCT tags.id) = 2')
我给你拆解下这段代码的逻辑:
joins(:tags):通过HABTM的关联关系,把products表和tags表正确连接起来,这一步就解决了表找不到的问题where(tags: { name: [...] }):先筛选出关联了这两个标签中任意一个的产品group('products.id'):把结果按产品ID分组,方便统计每个产品关联的标签数量having('COUNT(DISTINCT tags.id) = 2'):只保留那些关联了2个不同标签的产品,也就是同时拥有你要的两个标签的产品
如果之后经常需要做这种“同时拥有多个标签”的筛选,还可以把逻辑封装成模型的scope,复用性更强:
在app/models/product.rb里添加:
scope :with_all_tags, ->(tag_names) { joins(:tags) .where(tags: { name: tag_names }) .group(:id) .having("COUNT(DISTINCT tags.id) = ?", tag_names.size) }
然后在controller里就可以简化成:
@products = Product.with_all_tags(['Limestones', 'Mouldings'])
这样不管之后要筛选几个标签,只要把标签名数组传进去就行,非常方便~
内容的提问来源于stack exchange,提问作者Charles Smith
相关产品推荐
相关产品推荐

