2

編集 - 「includes」を使用すると、SQL の「IN」句が生成されます。Oracle を使用する場合、これには 1,000 アイテムの制限があります。それは私の会社ではうまくいきません。そこに他の解決策はありますか?

アソシエーションにアソシエーションを熱心にロードすることは可能ですか?

たとえば、アカデミーのクラスがあり、アカデミーに多くの生徒がいるとします。各生徒は、student_level に所属しています

class Academy < ActiveRecord::Base
  has_many :students
end

class Student < ActiveRecord::Base
  belongs_to :academy
  belongs_to :student_level
end

class StudentLevel < ActiveRecord::Base
  has_many :students
end

アカデミーで関連付けを調整して、生徒をロードするときに常に生徒のレベルを生徒にロードすることはできますか?

つまり、次のコード セクションで、すべての生徒に対して 1 つのクエリではなく、合計 1 つまたは 2 つのクエリを生成するようにします。

@academy.students.each do |student|
  puts "#{student.name} - #{student.student_level.level_name}"
end

学生をアソシエーションからメソッドに変更すればこれができることはわかっていますが、他のクエリで学生をアソシエーションとして参照できないため、そうしたくありません。次の方法でSQLでこれを実行できることも知っていますが、デフォルトのスコープが変更されるたびにfinder_sqlを更新する必要があるため、関連付けにfinder_sqlを使用せずにこれを実行する方法があるかどうかを知りたいです。関連付けをプリロードしない:

SELECT students.*, student_levels.* FROM students
LEFT JOIN student_levels ON students.student_level_id = student_levels.id
WHERE students.academy_id = ACADEMY_ID_HERE
4

1 に答える 1

5

includesデータを熱心にロードするために 使用してみましたか?

class Academy < ActiveRecord::Base
  has_many :students

  # you can probably come up with better method name
  def students_with_levels
    # not sure if includes works off associations, see alternate below if it does not
    self.students.includes(:student_level)
  end

  def alternate
    Student.where("academy_id = ?", self.id).includes(:student_level)
  end
end

参照: http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

3 つのクエリが返されるはずです

  • アカデミーでの最初の発見
  • Student オブジェクトのコレクションのクエリ
  • それらのすべての Students StudentLevel オブジェクトのクエリ

追加:

# the same can be done outside of methods
@academy.students.includes(:student_level).each do |student|
  puts "#{student.name} - #{student.student_level.level_name}"
end

Student.where("academy_id = ?", @academy.id).includes(:student_level).each do |student|
  puts "#{student.name} - #{student.student_level.level_name}"
end

ActiveRelation クエリもチェーン可能です

@academy.students_with_levels.where("name ILIKE ?", "Smi%").each do # ...

関連する ActiveRecord クエリ (メソッド) のカプセル化に関する素敵な記事 - http://ablogaboutcode.com/2012/03/22/respect-the-active-record/

于 2013-05-11T15:55:24.853 に答える