With Rails 4, Model.scoped is deprecated, but Model.all cannot replace it

Running Rails 4, Model.scoped now deprecated.

DEPRECATION WARNING: Model.scoped is deprecated. Please use Model.all instead.

But there is a difference in Model.scoped and Model.all , that is, scoped.scoped returns the scope, and all.all launches the request.

In Rails 3:

 > Model.scoped.scoped.is_a?(ActiveRecord::Relation) => true 

In Rails 4:

 > Model.all.all.is_a?(ActiveRecord::Relation) DEPRECATION WARNING: Relation#all is deprecated. If you want to eager-load a relation, you can call #load (eg `Post.where(published: true).load`). If you want to get an array of records from a relation, you can call #to_a (eg `Post.where(published: true).to_a`). => false 

There are usage examples in libraries / issues that return scoped when there is a condition to do something or nothing, for example:

 module AmongConcern extend ActiveSupport::Concern module ClassMethods def among(ids) return scoped if ids.blank? where(id: ids) end end end 

If you change this scoped to all , you will run into random problems depending on where among used in the scope chain. For example, Model.where(some: value).among(ids) will run a query instead of returning a scope.

I want to use the idempotent method on ActiveRecord::Relation , which simply returns the scope.

What am I supposed to do here?

+75
activerecord ruby-on-rails-4
Aug 13
source share
4 answers

scoped where(nil) seems to be a real scoped replacement that works on both Rails 3 and 4 .: (

+58
Aug 13 '13 at 1:32
source share

In Rails 4.1 (beta 1), the following works:

 Model.all.all.is_a?(ActiveRecord::Relation) => true 

So it looks like this problem has been fixed, and in 4.1.0 Model.scoped has been completely removed.

+24
Dec 26 '13 at 20:48
source share

As mentioned in one of the comments, all should return an area according to the docs .

The docs are correct - it returns ActiveRecord :: Relation, but you need to use a half-time if you want to see it in the console:

 pry(main)> u = User.all; pry(main)> u.class => ActiveRecord::Relation::ActiveRecord_Relation_User 
+9
Dec 02 '13 at 20:19
source share

In addition to using where(nil) you can also call clone if you know that self is a relation and gets the same scoped call scoped without arguments, without warning of obsolescence.

EDIT

Now I use this code as a replacement for the scoped replacement, since I don't like to use where(nil) everywhere to get the current scope:

  # config/initializers/scoped.rb class ActiveRecord::Base # do things the modern way and silence Rails 4 deprecation warnings def self.scoped(options=nil) options ? where(nil).apply_finder_options(options, true) : where(nil) end end 

I do not understand why the authors of AR could not do something like this, since the OP tells all and scoped do not behave the same way.

+4
Aug 20 '13 at 5:57 on
source share



All Articles