使用Rails 4,Model.scoped已被弃用,但Model.all不能替代它
启动Rails 4, Model.scoped
已经被弃用了。
DEPRECATION WARNING: Model.scoped is deprecated. Please use Model.all instead.
但是, Model.scoped
和Model.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 (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
图书馆/关注中有用例,当有条件做某事或没做时返回scoped
,如下所示:
module AmongConcern extend ActiveSupport::Concern module ClassMethods def among(ids) return scoped if ids.blank? where(id: ids) end end end
如果您将scoped
更改为all
scoped
,您将面临随机问题,具体取决于在范围链中使用哪个范围。 例如, Model.where(some: value).among(ids)
将运行查询,而不是返回范围。
我想要的是在ActiveRecord::Relation
上的幂等方法,它只是返回一个范围。
我应该在这里做什么?
看来, where(nil)
是scoped
的真正的替代,这对Rails 3和4都有效。:(
在Rails 4.1(testing版1)上,以下工作:
Model.all.all.is_a?(ActiveRecord::Relation) => true
所以看来这个问题已经解决了,在4.1.0中Model.scoped
已经完全被删除了。
正如其中一条评论所提到的, all
应该根据文档返回一个范围。
文档是正确的 – 它返回一个ActiveRecord :: Relation,但是如果你想在控制台中看到它,你必须使用分号。
pry(main)> u = User.all; pry(main)> u.class => ActiveRecord::Relation::ActiveRecord_Relation_User
除了使用where(nil)
之外,如果你知道self
是一个Relation,并且调用scoped
时没有参数,那么你也可以调用clone
,这样可以避免使用deprecation警告。
编辑
我现在使用这个代码作为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指出all
和scoped
行为都不一样。