2012-03-15 6 views
10

ActiveRecord :: Relationを返す他のActiveRecordクラスメソッドよりスコープの利点を見出そうとしている10ページ以上を調べました。なぜ同じことをし、その下の選択肢よりも優れているスコープ、たとえば次のようにスコープの本当のメリット

:何度も

#scope :pat1, lambda {{:conditions => ["name like ?", 'J%']}}  
    #scope :pat2, lambda {{:conditions => ["id > 5"]}} 

    def self.pat1 
    where("name like ?", 'J%') 
    end 

    def self.pat2 
    where("id > 5") 
    end 

    def patx 
    self.class.pat1.pat2.first 
    end 

ドキュメントが再び彼らは連鎖させることができますので、スコープが有益であることを述べています...

"すべてのスコープメソッドは、他のスコープなどのメソッドを呼び出せるようにするActiveRecord :: Relationオブジェクトを返します。 - guides.rubyonrails.org

に「スコープは、プレーンクラスメソッドよりも優れている主な理由は、彼らが他の方法と連鎖させることができるということです」 http://ruby.railstutorial.org

...しかし、上記の代替も生産連鎖させることができます同じ結果。

ここでは天皇の新しい服があるかどうかを調べようとしています。構文上の観点からも、何のメリットもないようです。それらはより速く - 一部の情報源はそれを曖昧に示唆しています。

答えて

3

ActiveRecordスコープは、すでに述べたように、実際には単に砂糖を包んだベストプラクティスです。

Railsの2.x日で、「named_scope」と呼ばれると、もう少し重要なものでした。それらは、クエリを生成するための条件の連鎖を容易にしました。 ArelのRails 3.xの改良により、あなたが指摘したように、クエリ関係の関数を作成するのは簡単です。スコープは連鎖可能な事前定義された照会のためのシンプルで洗練されたソリューションを提供するだけです。すべてのスコープをモデルの上部に置くと、読みやすさが向上し、モデルの使用方法がわかります。

+0

Arel私はActiveRecord :: Relationを意味すると仮定しています。 OK。構文上の利点は私には議論の余地があるようです。しかし、もし彼らが以前のバージョンでは標準的な方法ではできないことをしていたら、それはそれを説明します。 – Mark

+2

より良い構文を使用するレールが重要です。 1日目(または100日目)のコードベースではなく、1000日目のコードベース用です。 –

2

はい、構文上のショートカットは、基本的にあなたが見つけたメソッドを表しています。
なぜ良いですか?
最も直接的な効果は、2行のコードが9行のコードよりも読みやすく保守が容易であることです。

Railsは常にDRYアプローチを求めており、ここではdef self.method endが繰り返し実際のコードを覆い隠しています。

+0

あなたとSean Hillのおかげで、スピードの問題ではないことを確認しました。上記のrailstutorial.orgのリンクは、スコープを使用した代替実装がやや高速ですが、スコープを使用していることと明らかに関連していないことを具体的に示しています。 – Mark

3

スコープを書くときは、本質的に同じことをしています。

def scope(name, scope_options = {}) 
     name = name.to_sym 
     valid_scope_name?(name) 
     extension = Module.new(&Proc.new) if block_given? 

     scope_proc = lambda do |*args| 
     options = scope_options.respond_to?(:call) ? unscoped { scope_options.call(*args) } : scope_options 
     options = scoped.apply_finder_options(options) if options.is_a?(Hash) 

     relation = scoped.merge(options) 

     extension ? relation.extending(extension) : relation 
     end 

     singleton_class.send(:redefine_method, name, &scope_proc) 
    end 

この場合にはスコープに利点は、彼らはいくつかのケースでは、少ないコード行をクエリの定義の慣用的な方法であるということである、とあなたが拡張を行うことができます:ここではRailsのソースは次のようになります。

ソースの例は以下のようになります。あなたがModel.red.dom_idを呼び出すことができます

scope :red, where(:color => 'red') do 
    def dom_id 
    'red_shirts' 
    end 
end 

を。

0

スコープとリレーションを返すクラスメソッドの間には、非常に興味深い違いがいくつかあります。

  1. paramはnilの関係を引き起こす場合は、明示的に非nilの関係を返さなければならないクラスメソッドで簡単なparam.present?チェック、とスコープのnilのパラメータに対処する方が簡単です。

  2. スコープは、クラスメソッドよりも拡張が容易です。メソッドを追加するには、ブロックを渡します(たとえば、ページネーションを処理するなど)。クラスメソッドは拡張できますが、エレガントではありません。

this post from Plataformatecを参照してください。

関連する問題