74

In my Rails app have a default scope that looks like this:

default_scope order: 'external_updated_at DESC'

I have now upgraded to Rails 4 and, of course, I get the following deprecation warning "Calling #scope or #default_scope with a hash is deprecated. Please use a lambda containing a scope.". I have successfully converted my other scopes but I don't know what the syntax for default_scope should be. This doesn't work:

default_scope, -> { order: 'external_updated_at' }
Joe Gatt
  • 2,197
  • 3
  • 15
  • 19
  • Related: should default_scope be [avoided altogether](https://github.com/rails/rails/issues/13965#issuecomment-34407465), and what are some alternative approaches? – Jay Nov 11 '14 at 18:18

8 Answers8

152

Should be only:

class Ticket < ActiveRecord::Base
  default_scope -> { order(:external_updated_at) } 
end

default_scope accept a block, lambda is necessary for scope(), because there are 2 parameters, name and block:

class Shirt < ActiveRecord::Base
  scope :red, -> { where(color: 'red') }
end
blnc
  • 4,384
  • 1
  • 28
  • 42
Luke
  • 3,381
  • 1
  • 20
  • 20
  • Thanks for the explanation, Luke. I got a syntax error, then I changed it to default_scope { order('external_updated_at') } and it worked. Can you edit your answer, please, so I can accpet it? – Joe Gatt Aug 29 '13 at 09:08
  • 6
    This didn't work for me in 4.0.2 without the arrow. My working solution was ```default_scope -> { order_by(:created_at => :desc) }``` – genkilabs Feb 07 '14 at 01:31
  • 1
    By convention, symbols are preferred when referencing attributes. `default_scope { order(:external_updated_at) }` – scarver2 Aug 11 '14 at 21:05
  • 3
    BTW The correct answer to @JoeGatt question is `default_scope order('external_updated_at DESC')` – scarver2 Aug 11 '14 at 21:22
  • This does not address ordering if you have results that have varied case (upcase vs. downcase)... any thoughts on ordering via default_scope while forcing downcase? – Kees Briggs May 24 '15 at 19:59
21

This is what worked for me:

default_scope  { order(:created_at => :desc) }
Baby Groot
  • 4,637
  • 39
  • 52
  • 71
qubit
  • 769
  • 6
  • 18
7

This also worked for me:

default_scope { order('created_at DESC') }

Alex Hawkins
  • 616
  • 7
  • 10
2

This worked from me (just for illustration with a where) because I came to this topic via the same problem.

default_scope { where(form: "WorkExperience") }
FastSolutions
  • 1,809
  • 1
  • 25
  • 49
2

You can also use the lambda keyword. This is useful for multiline blocks.

default_scope lambda {
  order(external_updated_at: :desc)
}

which is equivalent to

default_scope -> { order(external_updated_at: :desc) }

and

default_scope { order(external_updated_at: :desc) }
Chris McKnight
  • 8,540
  • 4
  • 29
  • 31
1

This works for me in Rails 4

default_scope { order(external_updated_at: :desc) }
Hovo
  • 455
  • 4
  • 9
0
default_scope -> { order(created_at: :desc) }

Don't forget the -> symbol

Abel
  • 3,989
  • 32
  • 31
0
default_scope { 
      where(published: true) 
}

Try This.

Hamza Zafeer
  • 2,360
  • 13
  • 30
  • 42