2 flat logo on transparent 256
2018-03-11

Ruby On Railsのscopeメソッドで検索を効率化する

177598

Ruby On Railsでは複数のModelで利用されているSQLや 複数のアクションで利用されているSQLを 1つにまとめるscopeメソッドがあります。

今回はこのscopeメソッドについて解説します。

なおそもそもRuby On RailsのSQLを呼び出すメソッドが分からない方は Ruby On Rails でデータを取得するメソッド一覧 の記事をご覧ください

scopeの使い所

原則、ControllerにはSQLの情報を記載すべきではないので、 複数のSQL条件が発生した場合は、scopeでまとめた方がよいです。

scopeの基本的な使い方

scopeは下記構文で、対象のモデルへ記載します。

scope :scope名, -> { sql文を記載 }

●実用例●

Articleモデル

class Article < ActiveRecord::Base

  scope :by_publish_time, -> { order(publish_time: :desc) }

end

articlescontrollerで設定したscope(bypublish_time)を呼び出す。

class ArticlesController < ApplicationController

  def index
    @articles = Article.all.by_publish_time
  end

  def categories
    @category_articles = Category.articles.by_publish_time
  end

end

scopeをクラスメソッドの様に利用する

.selfでクラスメソッドの様にscopeを利用することも可能です

Articleモデル

class Article < ActiveRecord::Base

  def self.publish_time
     order(publish_time: :desc)
  end

end

articles_controller

class ArticlesController < ApplicationController

  def index
    @articles = Article.all.publish_time
  end

  def categories
    @category_articles = Category.articles.publish_time
  end

end

scopeに引数を設定する

Articleモデル

class Article < ActiveRecord::Base

  scope : track_count, ->(count) { where("track_count < ?", count) }

end

articles_controller

class ArticlesController < ApplicationController

  def index
    @articles = Article.track_count(20)
  end

end

実行結果

SELECT "articles".* FROM "articles" WHERE (track_count < 20)

scope同士をマージする

メソッドチェーンでscopeをマージすることもできます

Articleモデル

class Article < ActiveRecord::Base

  scope : open, -> { where status: 'open' }
  scope : by_publish_time, -> { order(publish_time: :desc) }
end

articles_controller

class ArticlesController < ApplicationController

  def index
    @articles = Article.open.by_publish_time
  end

end

デフォルトスコープの設定

指定したモデルに設定した条件を全て当てはめる、default_scopeというメソッドもあります。

紹介はしますが思いがけないエラーが発生するため 推奨されていないので、利用は控えてください

Articleモデル

class Article < ActiveRecord::Base

  default_scope { order(publish_time: :desc) }

end

articles_controller

class ArticlesController < ApplicationController

  def index
    #デフォルトscopeを呼び出す際はメソッドを指定しなくても適用される。
    @articles = Article.all
  end

end

以上です。

その他の関連記事

Ruby On Railsでredcarpetを利用し、シンタックスハイライトに対応したブログ機能を実装する

Ruby On Rails でデータを取得するメソッド一覧

ユーザーのフラグ管理に使えるRuby On Railsのenumを紹介

【初心者・独学者向け】Ruby On Railsで中間テーブルを作成し、多対多を実現する

Ruby On Railsのwhereで順序どおりに値を取得する

Ruby On Rails でページネーションを設定する

前の記事
次の記事