railsのscope / named_scopeとは何ですか?


105

最近インターンシップを始めました。私の雇用主はRuby on Railsを使用しており、理解するために調べる必要がある新しい構文に頻繁に遭遇します。named_scopeの適切な説明を探してググってみましたが、これまでに見つけたものは、ほとんどが、ストレートな定義や紹介ではなく、高い評価を得ているブログ投稿です。

Ruby on Railsのnamed_scope(現在は単にスコープと呼ばれる)とは正確には何ですか?



2
:スコープという名前の学習と、このブログの記事は、私にとって非常に貴重だったryandaigle.com/articles/2008/8/20/...
ピーター・ブラウン

@notapatchリンクが無効になっています。別のリンクがありますか?
mbigras

ライアン
デイグル

回答:


212

スコープはコレクションのサブセットです。複雑に聞こえますか?そうではありません。これを想像してみてください:

ユーザーがいます。現在、これらのユーザーの一部はニュースレターを購読しています。ユーザーデータベースにフィールドを追加して、ニュースレターを受け取る人にマークを付けました(user.subscribed_to_newsletter = true)。当然、ニュースレターを購読しているユーザーを取得したい場合があります。

もちろん、いつでもこれを行うことができます。

User.where(subscribed_to_newsletter: true).each do #something

ただし、常にこれを書く代わりに、次のようにすることができます。

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, where(subscribed_to_newsletter: true)
  #yada yada
end

Rails 4以降を使用している場合は、代わりに次のようにします。

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, -> { where(subscribed_to_newsletter: true) }
  #yada yada
end

これにより、次のようにするだけでサブスクライバーにアクセスできます。

User.newsletter.each do #something

これは非常に単純な例ですが、一般的にスコープは作業を簡単にするための非常に強力なツールです。

このリンクを確認してください:APIの説明


7
「subscribedUsers」と呼ばれるユーザークラスでメソッドを定義するよりも、これの利点は何ですか?例: 'def self.subscribedUsers self.where(:subscribed_to_newsletter => true)end
redroot

3
@redrootの利点は、scope構文がよりクリーンで、同じ結果が得られるが、1行だけである
Aldo 'xoen' Giambelluca

9
@redroot以前は効率が非常に優れていました。スコープがデータベースを遅延クエリする一方で、メソッドは熱心にクエリを実行するためです。Rails 3では、メソッドも遅延していたため、違いはより構文的になりました。出典
evanrmurphy 2013年

APIドキュメントのリンクが壊れていますapi.rubyonrails.org/classes/ActiveRecord/Scoping/Named/…
Lohith MV

スコープルートリンクの
Benjineer 2014

34

アクティブレコードのスコープはクラスメソッドに似ていますが、Relationオブジェクトを返します。つまり、別のスコープまたはアクティブレコードクエリメソッドを呼び出すことができます。

たとえば、以下に説明するスコープメソッドを持つゾンビモデル(ゾンビテーブル)がある場合、

class Zombie
  scope :rotting, -> { where(rotting: true) }
  scope :fresh, -> { where('age < ?', 25) }
  scope :recent, -> { order(created_at: :desc) }
end

そしてあなたは呼ぶ

Zombie.rotting.fresh.recent.limit(3)

それはSQLで以下に変換されます、

select "zombies.*" from "zombies" where "zombies"."rotting" = 't' and (age<20) order by create_at desc limit 3

上記の例は、rails 4構文に基づいています


どのドキュメントにもorder(:created_at、:desc)の例が見つかりません。あなたが意味したことは可能ですscope :recent, -> { order(created_at: :desc) }か? apidock.com/rails/v4.2.9/ActiveRecord/QueryMethods/order
notapatch


7

スコープはクラスメソッドにすぎません。

なぜそれらを使うのですか?

スコーピングを使用すると、関連オブジェクトまたはモデルのメソッド呼び出しとして参照できる、一般的に使用されるクエリ(長いクエリまたは最も頻繁に使用されるクエリのショートカットと見なすことができます)を指定できます。これらのスコープを使用すると、以前にカバーしたすべての方法(where、join、includeなど)を使用できます。すべてのスコープメソッドは、ActiveRecord :: Relationオブジェクト返します。これにより、他のスコープなどのメソッドを呼び出すことができます。

単純なスコープを定義するには、クラス内でスコープメソッドを使用し、このスコープが呼び出されたときに実行するクエリを渡します。

class Article < ActiveRecord::Base
  scope :published, -> { where(published: true) }
end

これは、クラスメソッドを定義するのとまったく同じです。どのメソッドを使用するかは、個人的な好みの問題です。

class Article < ActiveRecord::Base
  def self.published
    where(published: true)
  end
end

例の完全な説明については、次のリンクをたどってください。これがお役に立てば幸いです。

http://guides.rubyonrails.org/active_record_querying.html


3
これは、クラスメソッドの定義とまったく同じではありません。クラスメソッドnilはいくつかのケースで戻るため、特定の条件では連鎖できません。
Arslan Ali

1
  • 次のモデルがあるとします:Person

今あなたを想像してみてください:

  • 赤い髪を持っている世界のすべての人々が欲しい。
  • クリケットをする世界中のすべての人々が欲しい

スコープを使用して、特定のクラスの人々を取得できます。

Person.red_hair.cricket ## finds all people with red hair who play cricket
Person.red_hair ## finds all people with red hair
Person.cricket ## finds all people who play cricket.

今はそれほど難しくありませんでしたか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.