2

Railsにオブジェクト全体(ほんの数フィールド)を構築させずに、ActiveRecordを介してDBからオブジェクトをフェッチする方法があるかどうか疑問に思っています。

たとえば、特定のオブジェクトに特定のフィールドが含まれているかどうかを確認する必要がある場合があります。Bagオブジェクトを参照するStudentオブジェクトがあるとします(各学生には1つのバッグがあります)。バッグに鉛筆が4本以上ある女子学生がいるかどうかを確認する必要があります。

ActiveRecordでは、次のようなことをする必要があります。

exists = Student.female.find(:all, conditions => 'bags.pencil_count > 4', :include => :bag).size > 0

問題は、この条件に準拠する学生が1000人いる場合、1000個のバッグを含む1000個のオブジェクトがARによって作成されることです。

これにより、(パフォーマンス上の理由から)このクエリにプレーンSQLを使用することになり、ARが壊れます。名前付きスコープは使用しません。名前付きスコープ内の何かが変更された場合は、コード全体でスコープを更新することを忘れないでください。

これは例ですが、パフォーマンス上の理由から、ARに多くのオブジェクトを構築させる代わりにSQLを使用する必要があり、これによりカプセル化が機能しなくなる場合が多くあります。

ARにオブジェクトを作成しないように指示する方法、または特定のフィールドを作成するように指示する方法はありますか(アソシエーションでも)?

4

2 に答える 2

4

一致するレコードの存在のみをテストする場合は、Model.countfrom ActiveRecord::Calculationsを使用します。例:

exists = Student.female.count(  :conditions => 'bags.pencil_count > 4',
                                :joins => :bag
                             ) > 0

count単純に (クラスの名前が示すように)、計算を行い、オブジェクトを構築しません。

(また、今後の参考のために、 と の違いを知っておくとよいでしょう:include:joins前者は関連付けられたモデルを熱心にロードしますが、後者はそうではありませんが、これらのフィールドを で使用できます:conditions。)

于 2011-06-21T07:44:35.837 に答える
2

ジョーダンはここで最良の答えを出しました-特に re: インクルードの代わりにジョインを使用します (ジョインは実際にはバッグオブジェクトを作成しないため)

「Student」オブジェクトが実際にまだ必要な場合 (わずかな情報のみ)、:select キーワードを使用することもできます。これは mysql と同じように機能し、データベース I/O は、select に入力した情報だけに削減されます。また、他のテーブルから派生フィールドを追加することもできます。

students = Student.female.all( 
               :select => 'students.id, students.name, bags.pencil_count AS pencil_count', 
               :conditions => 'students.gender = 'F' AND bags.pencil_count > 4',
               :joins => :bag
               )
students.each do |student|
  p "#{student.name} has #{student.pencil_count} pencils in her bag"
end

たとえば、次のようになります。

Jenny has 5 pencils in her bag
Samantha has 14 pencils in her bag
Jill has 8 pencils in her bag

(ただし、派生フィールド (例: pencil_count) は文字列になることに注意してください。たとえば、 Student.pencil_count.to_i を使用してキャストする必要がある場合があります)。

于 2011-06-21T08:25:42.880 に答える