在Rails 4中,不赞成使用Model.scoped,但是Model.all不能替代它


76

Model.scoped现在不建议使用Rails 4 。

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

但是,有一个区别Model.scopedModel.all,那就是scoped.scoped返回一个范围,而all.all运行查询。

在Rails 3上:

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

在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 (e.g. `Post.where(published: true).load`). If you want to get an array of records from a relation, you can call #to_a (e.g. `Post.where(published: true).to_a`).
=> false

库/关注中存在用例,scoped当有条件做某事或什么都不做时会返回,例如:

module AmongConcern
  extend ActiveSupport::Concern

  module ClassMethods
    def among(ids)
      return scoped if ids.blank?

      where(id: ids)
    end
  end
end

如果将其更改scopedall,您将面临随机问题,具体取决于among范围链中使用的位置。例如,Model.where(some: value).among(ids)将运行查询而不返回范围。

我想要的是ActiveRecord::Relation仅返回范围的幂等方法。

我应该在这里做什么?


您确定“all运行查询”的东西不仅仅是控制台的人工产物吗?消息人士认为它应该可以正常工作。
亩太短了


但是,你没有得到该警告这样你得到allscoping/named.rb,对不对?而allscoping/named.rb是,据我所知,有什么Model.all用途。
亩太短了


Answers:


63

似乎where(nil)是对的真正替代scoped,它在Rails 3和4上均可使用。:(


55
哦我的天哪!真的吗?WTF。
大卫,

1
弃用警告说要使用load
shanemcd

它说要使用loadIF并希望加载它,并且无论如何都需要一个参数(条件),所以到目前为止where(nil)(ortrue{}or 1)似乎是scoped
ecoologic

不适合我的情况:user.active_section.scoped.uniq(false)有效user.active_section.all.uniq(false)user.active_section.where(nil).uniq(false)无效。
Skully 2014年

Rails 5怎么样?
Chamnap

25

在Rails 4.1(测试版1)上,可以进行以下工作:

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

因此,此问题似乎已解决,并且在4.1.0Model.scoped中已完全删除。


2
太好了,谢谢您的更新!但是,如果您是宝石维护者,则必须继续使用where(nil)直到不支持4.0.x ...
kenn 2013年

这是一个非常老的线程,但是我们仅在现在进行升级,并且还必须保持对Rails 3和4的支持。按照以下方式做点事合理if ActiveRecord::VERSION::MAJOR == 3 then Model.scoped else Model.all end吗?
astorije

9

如评论之一所述,all应该根据docs返回范围。

该文档是正确的-它确实返回ActiveRecord :: Relation,但是如果要在控制台中看到它,则必须使用分号:

pry(main)> u = User.all;

pry(main)> u.class

=> ActiveRecord::Relation::ActiveRecord_Relation_User

无关紧要-尝试User.all.all;,您会收到相同的警告。不幸的是,直到Rails 4.x甚至是Rails 5都不会修复。github.com
kenn

4

除了使用where(nil)您也可以拨打clone如果您知道self是一个关系,并得到调用的相同的行为scoped与无参数,SANS弃用警告。

编辑

我现在将这段代码用作替代代码,scoped因为我不喜欢where(nil)在任何地方都需要掌握当前范围:

     # 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

我不明白为什么AR作者不能有,因为作为OP点了类似的做了一些allscoped相同的行为。


您不能调用clone模型类。(例如Model.clonescoped同时处理模型类和关系。
肯恩

@kenn Yep,因此,为什么我在上面说“如果你知道自我是一种关系”。
Andrew Hacking 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.