2011-02-20 4 views
1

Personモデルオブジェクトは、単一のクエリで集計できない複雑な基準に基づいてソートしたいので、名前付きスコープでもソートします。今私はクラスメソッドを使用しています:注文連鎖可能

def Person.very_complicated_sorting 
    Person.all.sort { |x,y| x.bunch_of_calculations <=> y.bunch_of_calculations } 
end 

これをチェーン化する方法はありますか?例えば。

Person.tallest.very_complicate_sorting.youngest 

どこtallestyoungestは、2つの名前付きスコープです。

+1

「sort_by」は、ブロックに1つのパラメータしか与えず、2つではありません。私はあなたが '.sort_by {| x | x.bunch_of_calculations} ' – Dogbert

+0

私はちょうど「ソート」を意味しました、申し訳ありません!(編集済み) –

答えて

1

これは残念ながらできません。

スコープの仕組みは、実際に何かをしようとするまで評価されないSQLパラメータの組み合わせを「遅らせる」ことです。したがって、たとえば名前のスコープの次チェーン:

people = Person.tallest.youngest 

ない原因任意のデータベースクエリが実行されるだろう、それは実際にpeople変数に格納するActiveRecord::NamedScope対象になります。そのオブジェクトにアクセスまたは反復するときだけ、SQLが実行され、オブジェクトがロードされます。

あなたの問題は、ソート方法がSQLで表現されていないことです。これはRubyの条件のセットです。 Railsがsort_byに到達すると、Personオブジェクトをフェッチしてインスタンス化しなければならないので、あなたの条件を実行することができます。それが完了した後はのオブジェクトがあり、もうNamedScopeオブジェクトはありません。

0

very_complicated_sortingPersonモデルである必要があります。

Person.allをメソッド内に書き込まないようにしてください。それ以外の場合はチェーン化できません。

ちょうど保つ:

def self.very_complicated_sorting 
    sort_by { |x,y| x.bunch_of_calcultaions <=> y.bunch_of_calculations } 
end 
+0

これは私の 'Person'モデルです...そして、私はインスタンスメソッドではなく、クラスメソッドを必要としています! –

+0

それはクラスメソッドだった:) – apneadiving

+0

私のせい...自分自身を見ていない。たとえそれが質問に答えなかったとしても、提案は良かった! :) –

0

これは、データベースライブラリにActiveRecordの代わりにSequelを使用すると可能です。モデル上でdef_dataset_methodを使用してDatasets(モデルを含む)で動作するメソッドを作成できます。メソッドがデータセットを返す限り、好きなようにチェーンすることができます。例:

class Person < Sequel::Model 
    def_dataset_method :active_only do 
    filter :active=>true 
    end 
    def_dataset_method :sort_much do 
    order :name, :age.desc 
    end 
end 

active_peeps = Person.active_only.sort_much 
peeps_active = Person.sort_much.active_only 

データセットを使用するには、SQLで表現できるメソッドのみを使用する必要があります。データベースからいくつかのレコードを要求してから、複雑なRubyのみのロジックを実行する(例えば、object_idをRuby Hashで検索してソートする)ことはできません。そして結果の配列に対してSQLを引き続き実行します。 Rubyはデータベース上で実行されません(pl/Ruby以外)。

また、Ruby配列にまっすぐ行くことができます。そして、それらがすべて配列と戻り配列で動作している場合、任意のRubyメソッドを任意の順序でチェーンすることができます。データベースから結果をフェッチし、その後アレイで操作する予定があるかどうかについては、コードで明確に判断する必要があります。