web-dev-qa-db-ja.com

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 (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_上のべき等メソッドです。

ここで何をすべきですか?

77
kenn

where(nil)scopedの実際の置き換えであるようで、Rails 3と4の両方で動作します。

63
kenn

Rails 4.1(ベータ1))では、次のように動作します:

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

したがって、この問題は修正され、4.1.0でModel.scopedは完全に削除されました。

25
Olivier Lacan

コメントの1つで述べたように、allはスコープを返すはずです ドキュメントによると

ドキュメントは正しいです-ActiveRecord :: Relationを返しますが、コンソールで表示したい場合はセミコロンを使用する必要があります:

pry(main)> u = User.all;

pry(main)> u.class

=> ActiveRecord::Relation::ActiveRecord_Relation_User
9
Jason Rust

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がallscoped do notを同じように振る舞うので、ARの作者が同じようなことをできなかった理由はわかりません。

4
Andrew Hacking