简体   繁体   English

在ActiveRecord关联中使用FIELD

[英]Use FIELD in ActiveRecord association

I want to show posts that are tagged with the current locale first. 我想先显示用当前语言环境标记的帖子。 I thought that the MySQL FIELD function would be a nice way to solve this. 我认为MySQL FIELD函数将是解决此问题的好方法。

However, 然而,

Post.includes(:tags).order("FIELD(tags.name, '#{I18n.locale}') DESC").first

results in 结果是

Mysql2::Error: Unknown column 'tags.name' in 'order clause': SELECT  spree_posts`.* FROM 'spree_posts' ORDER BY FIELD(tags.name, 'en') DESC LIMIT 1

If I try 如果我尝试

Post.includes(:tags).order("FIELD(tags.name, '#{I18n.locale}') DESC").where.not(tags: { name: 'WTF?' } )

it returns the posts according to the FIELD method correctly, but does a join with tags, hence not returning all posts without tags :( 它会根据FIELD方法正确返回帖子,但是会使用标签进行联接,因此不会返回所有没有标签的帖子:(

I think this might be a bug in ActiveRecord? 我认为这可能是ActiveRecord中的错误? It's definitely not the behaviour I expect. 这绝对不是我期望的行为。

SELECT spree_posts`.* FROM 'spree_posts' ORDER BY FIELD(tags.name, 'en') DESC LIMIT 1 SELECT spree_posts`。* FROM'spree_posts'ORDER BY FIELD(tags.name,'e​​n')DESC LIMIT 1

There is no tags table in this query, the table is not loaded, because includes is a smart method, that generates JOIN only when included table is used in WHERE clause. 此查询中没有tags表,该表未加载,因为includes是一个智能方法,仅当在WHERE子句中使用包含表时才会生成JOIN

You need to explicitly define LEFT JOIN : 您需要显式定义LEFT JOIN

Post.joins('LEFT JOIN tags ON tags.post_id = post.id').order("FIELD(tags.name, '#{I18n.locale}') DESC").first

(by default joins generates INNER JOIN ) (默认情况下, joins生成INNER JOIN

If you want to use includes and ensure Rails loads the table in the main query, you should use references : 如果要使用includes并确保Rails在主查询中加载表,则应使用references

Post.includes(:tags).references(:tags).
  order("FIELD(tags.name, '#{I18n.locale}') DESC").first

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM