Reputation: 2770
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.
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 :(
I think this might be a bug in ActiveRecord? It's definitely not the behaviour I expect.
Upvotes: 1
Views: 40
Reputation: 468
If you want to use includes
and ensure Rails loads the table in the main query, you should use references
:
Post.includes(:tags).references(:tags).
order("FIELD(tags.name, '#{I18n.locale}') DESC").first
Upvotes: 1
Reputation: 954
SELECT spree_posts`.* FROM 'spree_posts' ORDER BY FIELD(tags.name, 'en') 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.
You need to explicitly define 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
)
Upvotes: 1