LoginSignup
2
2

More than 3 years have passed since last update.

【Rails】scopeの定義とProcオブジェクト

Posted at

scopeとは

よく利用する検索条件に名前をつけてひとまとめにしたもの。
railsガイドでは以下のように解説されています。

スコープを設定することで、関連オブジェクトやモデルへのメソッド呼び出しとして参照される、よく使用されるクエリを指定することができます。スコープでは、where、joins、includesなど、これまでに登場したすべてのメソッドを使用できます。どのスコープメソッドも、常にActiveRecord::Relationオブジェクトを返します。このオブジェクトに対して、別のスコープを含む他のメソッド呼び出しを行なうこともできます。

scopeの書き方

models/book.rb
class Book < ApplicationRecord
  scope :costly, -> { where("price > ?", 3000) }
end

scopeの第一引数にメソッド名、第二引数にProcオブジェクト(のラムダ)を定義することで、コントローラーやモデルでBook.costlyと書いたとき、Book.where("price > ?", 3000)と書いたのと同義になります。これによるメリットは以下の2つです。

  • 繰り返し利用できる
  • 可読性が向上する

何度もクエリを書かなくてよくなるのに加えて、Book.costlyとあれば、高価な本を探しているんだなとひと目で分かります。

また、引数を渡すこともできます。

models/book.rb
class Book < ApplicationRecord
  scope :written_about, ->(theme) { where("name like(?)", "%#{theme}%") }
end

scopeを定義した際の返り値のクラスはActiveRecord::Relationとなるので、scopeをメソッドチェーンでつなげたり、Query Interfaceを呼び出すこともできる。

Book.costly.written_about("ハリーポッター").limit(1)
=> #<ActiveRecord::Relation [
#<Book id: 1, name: "賢者の石", published_on: "1999-10-21", price: 4000>
]>

ブロックが複数行に渡る場合

scopeの第二引数はProcオブジェクトのラムダを使います。ブロックが複数行に渡る場合は下のような書き方が一般的です。

models/book.rb
scope :written_about, lambda { |theme|
  return if theme.blank?

  where("name like(?)", "%#{theme}%")
}

以上

補足

Procオブジェクトとは

ブロックをオブジェクト化したProcクラスのインスタンスです。

hello_proc = Proc.new { "hello" }
hello_proc.call
=> "hello"

Procオブジェクトの作成方法

Proc.new { |a, b| a + b }
proc { |a, b| a + b }
->(a, b) { a + b }
lambda { |a, b| a + b }

厳密には上2つと下2つのオブジェクトは異なります。下2つはラムダと呼ばれ、scopeの第二引数で使っているものです。ラムダは引数のチェックがより厳密です。検索条件で渡ってくる引数は決まっているため、ラムダを使っていました。

add_proc = Proc.new { |a, b| a.to_i + b.to_i }
add_proc(10)
#=> 10 

add_lambda = ->(a, b) { a.to_i + b.to_i }
add_lambda(10)
#=> ArgumentError: wrong number of arguments (given 1, expected 2)

Procオブジェクトの実行方法

add_proc = Proc.new { |a, b| a + b }

add_proc.call(10, 20)
add_proc.yield(10, 20)
add_proc.(10, 20)
add_proc[10, 20]

参考

https://railsguides.jp/active_record_querying.html#%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97
パーフェクトRuby on Rails

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2