SlideShare a Scribd company logo
named_scopeに
ついてくわしく
(株)永和システムマネジメント ¦¦ Rails勉強会@東京

 諸橋 恭介            (もろはし きょうすけ)



   k-morohashi@esm.co.jp (work)
  moronatural@gmail.com (private)
まとめ

• named_scopeを使うと、複雑な検索条
 件をシンプルかつ柔軟に記述できる

• 技術的にずいぶんおもしろい
 • とてもかっこいいmethod_missingの
  よい使い方
これはなに?

• かつてRailsには with_scope という
 APIがありました

• with_scopeを使うと、検索条件を指定
 する「スコープ」を定義できます

 • そのスコープ内での検索には、自動的
  にスコープの条件が付加されます
with_scopeの例
User.find(:all)
# SELECT * FROM users

User.find(:all, :conditions=>[“deleted=?”,false])
# SELECT * FROM users WHERE deleted = 0

User.with_scope(
  :find=>{:conditions=>[“deleted=?”,false]}) do
  User.find(:all)
end
# SELECT * FROM users WHERE deleted = 0
with_scopeについて

                Recipe 077 (p.220)

                検索条件をスコープ毎に
                まとめて定義する




http://www.amazon.co.jp/dp/4797336625
What’s
         named_scope?
•with_scopeで使っていた「検索スコー
  プ」に名前が付けられます。

•Rails 2.1の目玉機能です
 • RubyKaigi 2008でも松田さんが話しました
http://www.slideshare.net/a_matsuda/
  new-wave-of-database-programming-with-ruby-19-on-rails-21/
なにがすごいの?
•名前を付けたスコープ同士を掛け合わ
せられます。
•   DBアクセスは、 必要となった時点で賢く(多くは1回だ
    け)実行されます。


•「微妙に条件の異なる検索」の多くを
スコープの掛け合わせで表現できます
ORMとRDBMS
• RDBMSをOOPの世界に引っ張ってきた
 ORMはすごい!!

• しかしORMを使うと、RDBMSは単なる
 オブジェクトの永続化ストレージのように
 扱いがちです。

• named_scopeを使うと、RDBの集合演
 算が持つ力の一部をOOPの世界でも使える
 感じになります。
named_scopeの
     例
有効なユーザ
      users

active users
有効なユーザ
class User < ActiveRecord::Base
  named_scope(:active,
    {:condition=>["deleted = ?", false]})
end

describe “activeなユーザ” do
 it “は全員削除されて*いない*こと” do
    User.active.should be_all{|u| not u.deleted }
  end
end
人気のあるユーザ
実行時にscopeの一部を指定

     users

             hot users
人気のあるユーザ
       実行時にscopeの一部を指定

class User < ActiveRecord::Base
  named_scope :active,
   :condition=>["deleted = ?", false]

  named_scope :hot,
      Proc.new{|arg|
        {:conditions=>[“popularity > ?”, arg],
         :order =>"popularity DESC"}
    }
end
人気のあるユーザ
       実行時にscopeの一部を指定

describe “人気度80以上のユーザ” do
 before do
   @users = User.hot(80)
 end

 it "のうちトップはdahliaであること" do
    @users.first.should == users(:dahlia)
  end
end
人気かつ有効なユーザ
 crossover 2 scopes
       users

active users users
           hot
人気かつ有効なユーザ
               crossover 2 scopes
describe "BAN! dahlia" do
  before(:each) do
    # dahliaの削除フラグを立てる つまり active usersの集合から外す
    users(:dahlia).update_attribute(:deleted, true)
  end

  it "アクティブユーザで最も人気なのはcharlesであること" do
    User.active.hot(80).first.should == users(:charles)
  end

  it "クエリ発行(select_all)は一回だけ呼ばれること" do
    User.connection.should_receive(:select_all).once.and_return([])
    User.hot(80).active.find(:all)
  end
end
他にも好きな条件を
  追加できる
      users

active users n users
          hot

         Other..
named_scope
    実行時の動き
User.active.hot(80).each do |u|
  do_something
end
User.active.hot(80)
        - generate Scope instance -

User#active
#=> <#Scope:active, @proxy_scope=>User>


<#Scope:active>#hot(3)
---> <#Scope:active>#method_missing(:hot)

# scopes.include?(:hot)であるため
#=> <#Scope:hot, @proxy_scope=> <# Scope:active>>
Scope#method_missing


•User#activeはUserクラスを親ス
コープとしたScopeを作る

•Scope#method_missingは呼ばれた
メソッドに対応する子Scopeを作る
•   子Procには親スコープとしてselfを渡す
Scope#method_missing


def method_missing(method, *args, &block)
  if scopes.include?(method)
    scopes[method].call(self, *args)
  else
    with_scope :find => proxy_options do
       proxy_scope.send(method, *args, &block)
    end
  end
end
User.active.hot(80)
      - execute and respond to method -

<#Scope:hot, @proxy_scope=> <#Scope:active>>#each
---> <#Scope:hot>#proxy_found
---> <#Scope:hot>#find(:all)
---> <#Scope:hot>method_missing(:find)
---> <#Scope:hot>#with_scope{ <#Scope:active>#find }
---> <#Scope:active>#method_missing(:find)
---> <#Scope:active>#with_scope{   User.find(:all)   }
# => [<#User:..>, .... ]

[<#User:..>, ...].each{ do_something }
Scope#method_missing



•呼ばれたメソッドに対応するScope
が定義されていない場合
• 自身のfindパラメータでwith_scopeし、親ス
 コープの当該メソッドを呼び出す
Scope#method_missing


def method_missing(method, *args, &block)
  if scopes.include?(method)
    scopes[method].call(self, *args)
  else
    with_scope :find => proxy_options do
       proxy_scope.send(method, *args, &block)
    end
  end
end
with_scopeで
             書き直したイメージ
User.with_scope(
  :find=>{:conditions=>[”popularity>?”, 80],
          :order=>”popularity” }) do

  User.with_scope(
   :find=>{:conditons=>[“deleted=?”, false]}) do

   User.find(:all).each{ ... }

  end
end                    Rails2.xではこのままでは動きません
まとめ

• named_scopeを使うと、複雑な検索条
 件をシンプルかつ柔軟に記述できる

• 技術的にずいぶんおもしろい
 • とてもかっこいいmethod_missingの
  よい使い方
you.any?{|u|
  u.question?
}
FAQ: スコープはどんなふ
  うに結合されるの?
• 後ろから順にwith_scopeを使います。
 • WHERE句相当(:conditionsパラメータ)はANDで
  結合されます。

 • ORDERやLIMITは先に指定したscopeで指定して
  いるものがそのまま使われるっぽいです。

  •   この辺りのロジックは activerecord-2.1.0/lib/
      active_record/base.rb : 1807 あたりを参照
FAQ: Ruby 1.9だとより
カッコ良いという噂があるが?
 • Procオブジェクト生成に->記法が使えます
 旧
        named_scope :hot,
           Proc.new{|arg|
             {:order =>"popularity DESC",
 これが          :limit => arg}
         }

 こうなる   named_scope :hot, ->{
            {:order =>"popularity DESC",

 新       }
             :limit => arg}
FAQ: テストがよりカッコ良く
  書けるという噂があるが?
 • mockするのが楽にキレイになりそうな感じ。
 旧      User.should_receive(:find).
          with(:all,:condition=>[...]).
 これが      and_return( [alice] )


 こうなる
        User.shold_receive(:active)

 新        and_return( [alice] )
with_scopeについて

                Recipe 077 (p.220)

                検索条件をスコープ毎に
                まとめて定義する




http://www.amazon.co.jp/dp/4797336625
ご清聴
 ありがとう
ございました

More Related Content

PDF
[東京] JapanSharePointGroup 勉強会 #2
PDF
named_scope more detail
PPTX
T sql の parse と generator
PDF
CakeRequest::onlyAllow() について
PPTX
Powershell 超絶基礎 勉強会 v1 (もっと新しいバージョンがあります)
PPTX
運用構築技術者の為のPSプログラミング第1回
PDF
Elasticsearch入門 pyfes 201207
PPTX
PowerShell 小技集
[東京] JapanSharePointGroup 勉強会 #2
named_scope more detail
T sql の parse と generator
CakeRequest::onlyAllow() について
Powershell 超絶基礎 勉強会 v1 (もっと新しいバージョンがあります)
運用構築技術者の為のPSプログラミング第1回
Elasticsearch入門 pyfes 201207
PowerShell 小技集

What's hot (11)

PDF
WordPressで投稿記事情報の取得方法
PDF
RailsエンジニアのためのSQLチューニング速習会
PPTX
Powershell勉強会 v5 (こちらが最新です。)
PDF
データマイニング+WEB勉強会資料第6回
PPTX
Powershell勉強会 v2 (もっと新しいバージョンがあります)
PDF
PPTX
Powershell勉強会 v3 (もっと新しいバージョンがあります)
PDF
Apache Torqueについて
PDF
PerlとSQLのいろいろ
PPTX
Wpfと非同期
PDF
これからのpre_get_postsの話をしよう
WordPressで投稿記事情報の取得方法
RailsエンジニアのためのSQLチューニング速習会
Powershell勉強会 v5 (こちらが最新です。)
データマイニング+WEB勉強会資料第6回
Powershell勉強会 v2 (もっと新しいバージョンがあります)
Powershell勉強会 v3 (もっと新しいバージョンがあります)
Apache Torqueについて
PerlとSQLのいろいろ
Wpfと非同期
これからのpre_get_postsの話をしよう
Ad

Similar to named_scope more detail - WebCareer (20)

PDF
CodeIgniter入門
PDF
⑯jQueryをおぼえよう!その2
PDF
OSSから学ぶSwift実践テクニック
PDF
Grails 2.0.0.M1の話
PPTX
エンタープライズ分野での実践AngularJS
PDF
Elastic circle ci-co-webinar-20210127
PDF
PHPフレームワーク入門
KEY
activerecord-oracle_enhanced-adapterのご紹介
KEY
XPages 開発 Tips 百連発
PDF
脆弱性スキャナVuls(応用編)
PDF
Haikara
PDF
ZabbixのAPIを使って運用を楽しくする話
PDF
企業におけるSpring@日本springユーザー会20090624
PDF
EucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみました
PDF
20110820 metaprogramming
PPTX
Angular js はまりどころ
PDF
Web技術勉強会23回目
PPT
Inside mobage platform
PDF
AWS Black Belt Tech シリーズ 2015 - AWS Elastic Beanstalk
KEY
8分で分かる最近のCakePHP
CodeIgniter入門
⑯jQueryをおぼえよう!その2
OSSから学ぶSwift実践テクニック
Grails 2.0.0.M1の話
エンタープライズ分野での実践AngularJS
Elastic circle ci-co-webinar-20210127
PHPフレームワーク入門
activerecord-oracle_enhanced-adapterのご紹介
XPages 開発 Tips 百連発
脆弱性スキャナVuls(応用編)
Haikara
ZabbixのAPIを使って運用を楽しくする話
企業におけるSpring@日本springユーザー会20090624
EucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみました
20110820 metaprogramming
Angular js はまりどころ
Web技術勉強会23回目
Inside mobage platform
AWS Black Belt Tech シリーズ 2015 - AWS Elastic Beanstalk
8分で分かる最近のCakePHP
Ad

More from Kyosuke MOROHASHI (12)

PDF
Introduction HTTP via cURL
PDF
Ruby ecosystem applied to agile project
PDF
Test Context Arrangement Recipebook
PDF
Begin cucumber-in-real-world
PDF
Cucumber in Practice(en)
PDF
Rails testing environment, 2009 fall
PDF
TDD frameworks let me dream "Project Specific Language"
PDF
Rails Tokyo 035 Cucumber
PDF
OSC2008 勉強会大集合 Rails勉強会@東京
PDF
Capistrano in practice - WebCareer
PDF
Rails <form> Chronicle
PDF
そうだ勉強会に行こう
Introduction HTTP via cURL
Ruby ecosystem applied to agile project
Test Context Arrangement Recipebook
Begin cucumber-in-real-world
Cucumber in Practice(en)
Rails testing environment, 2009 fall
TDD frameworks let me dream "Project Specific Language"
Rails Tokyo 035 Cucumber
OSC2008 勉強会大集合 Rails勉強会@東京
Capistrano in practice - WebCareer
Rails <form> Chronicle
そうだ勉強会に行こう

named_scope more detail - WebCareer