The Artima Developer Community
Sponsored Link

Agile Buzz Forum
Be careful using default_scope and order()

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Dave Thomas

Posts: 85
Nickname: pragdave
Registered: Mar, 2003

Dave Thomas is...
Be careful using default_scope and order() Posted: Mar 26, 2012 4:48 PM
Reply to this message Reply

This post originated from an RSS feed registered with Agile Buzz by Dave Thomas.
Original Post: Be careful using default_scope and order()
Feed Title: PragDave
Feed URL: http://pragdave.blogs.pragprog.com/pragdave/atom.xml
Feed Description: The 'Practices' section of Dave Thomas's blog, including stuff on design, architecture, and the Code Kata exercises.
Latest Agile Buzz Posts
Latest Agile Buzz Posts by Dave Thomas
Latest Posts From PragDave

Advertisement

In a recent post, I talked about how the Rails first and limit/offset modifiers to queries are not specified to return a particular result—databases are free to determine the order of rows in a result set if the query doesn't contain an explicit order by clause, so the actual row(s) returned by these methods may not be determined.

Some folks responded (in comments, tweets, and emails) by suggesting that you can easily solve this problem by adding a default_scope call at the top of models that you use first and offset on. Ignoring the fact that this really isn't a solution (both the names first and offset imply an ordering which they don't deliver, and the fix should be in them); ignoring that, the suggestion might lead to another unexpected problem.

Lets start with a simple ActiveRecord model:

class Wish
end

Executing Wish.limit(10).offset(10).to_sql returns the SQL

SELECT  `wishes`.* FROM `wishes`  LIMIT 10 OFFSET 10

Noticing the lack of an order by clause, you add a default scope:

class Wish
  default_scope order(:id)
end

Now when we execute the query, the SQL contains an order by clause:

SELECT  `wishes`.* FROM `wishes` ORDER BY id LIMIT 10 OFFSET 10

Cool. Problem fixed.

However, the user also wants a list of the 3 most recent wishes, so you code

Wish.order("created_at desc").limit(3)

Imagine your chagrin when you look at the SQL that gets run and see

SELECT  `wishes`.* FROM `wishes` ORDER BY id, created_at desc LIMIT 3

Because the id column is unique, it totally determines the ordering—the created_at desc part of the query has no effect.

Once you add a default_scope with an order clause to a model, all subsequent finders on that model will have that order as their primary ordering. If you want some other order, you'll need to remember to add unscoped to the chain:

Wish.unscoped.order("created_at desc").limit(3)

And that's an accident waiting to happen.

 

 

 

Read: Be careful using default_scope and order()

Topic: Keep Me Company Previous Topic   Next Topic Topic: A subtle potential bug in most Rails applications

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use