Add ActiveRecord::QueryMethods#in_order_of.#42061
Conversation
|
Post.find([3, 5, 1]) already does this 😄. It's that original behavior that inspired in_order_of! See here: |
|
@dhh yeah but that returns an array of objects. This returns a relation that you can keep chaining, and add plucks onto the end. |
|
Ah I see. Do you have an example where you know all the IDs you want to fetch, but you want to chain it further still? How would this interact with ORDER etc? |
|
@dhh I probably wouldn't be ordering by ID. More likely you have something like: Post.in_order_of(:type, %w[Draft Published Archived]).order(:created_at).pluck(:name)which generates SELECT posts.name
FROM posts
ORDER BY
CASE posts.type WHEN 'Draft' THEN 1 WHEN 'Published' THEN 2 WHEN 'Archived' THEN 3 ELSE 4 END ASC,
posts.created_at ASCin MySQL, it's SELECT posts.name
FROM posts
ORDER BY
FIELD(posts.type, 'Archived', 'Published', 'Draft') DESC,
posts.created_at ASCIt's just another |
ad5cf15 to
c96e8e7
Compare
a018ff9 to
ddfbf77
Compare
This allows you to specify an explicit order that you'd like records
returned in based on a SQL expression. By default, this will be accomplished
using a case statement, as in:
```ruby
Post.in_order_of(:id, [3, 5, 1])
```
will generate the SQL:
```sql
SELECT "posts".* FROM "posts" ORDER BY CASE "posts"."id" WHEN 3 THEN 1 WHEN 5 THEN 2 WHEN 1 THEN 3 ELSE 4 END ASC
```
However, because this functionality is built into MySQL in the form of the
`FIELD` function, that connection adapter will generate the following SQL
instead:
```sql
SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESC
```
*Kevin Newton*
ddfbf77 to
459ca22
Compare
|
Rad as hell! Thanks 🙌 |
|
|
||
| def field_ordered_value(column, values) | ||
| field = Arel::Nodes::NamedFunction.new("FIELD", [column, values.reverse]) | ||
| Arel::Nodes::Descending.new(field) |
There was a problem hiding this comment.
Could this avoid reversing values with Arel::Nodes::Ascending?
There was a problem hiding this comment.
I can't 100% remember why I did this, but it has to do with mysql putting nulls first or last, so it needed to be this way. I'll see if I can find out why.
| *Luis Vasconcellos*, *Eileen M. Uchitelle* | ||
|
|
||
| * Fix `eager_loading?` when ordering with `Hash` syntax. | ||
| * Fix `eager_loading?` when ordering with `Hash` syntax |
Fix: rails#43903 Ref: rails#42061 Simply don't generate the case statement if the order list is empty and fallback to default ordering.
Summary
This allows you to specify an explicit order that you'd like records
returned in based on a SQL expression. By default, this will be accomplished
using a case statement, as in:
will generate the SQL:
However, because this functionality is built into MySQL in the form of the
FIELDfunction, that connection adapter will generate the following SQLinstead:
This work largely inspired by the new addition to Enumerable here: #41333. cc @dhh