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 (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
_
このscoped
をall
に変更すると、among
がスコープチェーンで使用されている場所に応じてランダムな問題に直面することになります。たとえば、Model.where(some: value).among(ids)
はスコープを返す代わりにクエリを実行します。
私が欲しいのは、スコープを返すだけの_ActiveRecord::Relation
_上のべき等メソッドです。
ここで何をすべきですか?
where(nil)
はscoped
の実際の置き換えであるようで、Rails 3と4の両方で動作します。
Rails 4.1(ベータ1))では、次のように動作します:
Model.all.all.is_a?(ActiveRecord::Relation)
=> true
したがって、この問題は修正され、4.1.0でModel.scoped
は完全に削除されました。
コメントの1つで述べたように、all
はスコープを返すはずです ドキュメントによると 。
ドキュメントは正しいです-ActiveRecord :: Relationを返しますが、コンソールで表示したい場合はセミコロンを使用する必要があります:
pry(main)> u = User.all;
pry(main)> u.class
=> ActiveRecord::Relation::ActiveRecord_Relation_User
where(nil)
の使用に加えて、clone
がリレーションであることがわかっている場合はself
を呼び出すこともでき、引数なしでscoped
を呼び出すのと同じ動作をします。 、廃止の警告はありません。
[〜#〜] edit [〜#〜]
現在のスコープを取得する必要があるすべての場所でwhere(nil)
を使用するのは好きではないので、私はこのコードをscoped
の代わりのドロップインとして使用しています。
# 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
OPがall
とscoped
do notを同じように振る舞うので、ARの作者が同じようなことをできなかった理由はわかりません。