2016-01-10 7 views
11

例:Ruby on Railsでは、has_many関係のスコープを作成するにはどうすればよいですか?

ReportCardオブジェクトとhas_many関係を持つStudentオブジェクトがあるとしましょう。 ReportCardオブジェクトには、段階的にフラグが立てられた「段階的」というブール値フィールドがあります。さて、あなたは生徒が何段階的ReportCardsを持っていない場合、あなたはそれらのすべてを見たいように、デフォルトのスコープを作成したいとしましょう

class Student < ActiveRecord 
    has_many :report_cards 
end 

class ReportCard < ActiveRecord 
    # graded :boolean (comes from DB) 
    belongs_to :student 
end 

が、彼らは、少なくとも一つの段階的なレポートカードを持っている場合:だから、それは次のようになりますあなたは格付けされたものだけを見たいと思っています。最後に、「semester_number」で注文するとします。レポートカードにこのスコープを使用して

は正しく動作:

scope :only_graded_if_possible, ->(student) { where(graded: true, student: student).order(:semester_number).presence || order(:semester_number) } 

しかし、私はので、私が試した、それは学生のためのデフォルトのスコープになりたい:

class Student < ActiveRecord 
    has_many :report_cards, ->{ where(graded: true).order(:semester_number).presence || order(:semester_number) } 
end 

をしかし、これは動作しません。 db全体に単一の採点report_cardがある場合、report_cardsは返されません。実行されたクエリを見ると、まず次のように実行されます。

SELECT report_cards.* FROM report_cards WHERE reports_cards.graded = t ORDER BY semester_number ASC 

これは現在のものでなければならないと思いますか?プレゼンスクエリの一部をチェックして、それが学生ではまったくフィルタリングされないことに注意してください。そこに傾斜された単一のreport_cardが、あるチェックが通過し、それを返すために何を取得するには、次のクエリを実行している場合ので:

SELECT report_cards.* FROM reports_card WHERE report_card.student_id = 'student id here' AND report_card.graded = t ORDER BY semester_number 

学生が段階的なレポートカードを持っていた場合、このクエリは、実際に正しいことだろうが、それ彼がしなければ常に空です。

おそらく、後でStudentのフィルタリングが追加されると考えています。この範囲では「自己」は、私が想定したいような学生対象ではないことが表示されますので、どちらかこれは動作しません

has_many :report_cards, ->{ where(graded: true, student: self).order(:semester_number).presence || order(:semester_number) } 

、しかし:だから私は何とかそれが右のバット学生をフィルタリングするために取得することを試みましたすべてのreport_card idsのリストこれは、この1つを実行するクエリです:

SELECT report_cards.* FROM report_cards WHERE report_cards.graded = t AND report_cards.student_id IN (SELECT report_cards.id FROM report_cards) ORDER BY semester_number ASC 

これは正しいものではありません。これをどのように機能させることができますか?

"has_many"で適用されているスコープへのパラメータとして、 "self"(現在のStudentオブジェクトを意味する)を渡すことができると思います。おそらくそれは不可能です。

+0

どのバージョンのRailsを使用していますか?私は避けるようにしようとしている何かをされた冗長 student.reports_cards(学生)に student.report_cards :協会から使用されるたびに変更が必要となる – Dani

答えて

2

あなたはこれを試してみてください

has_many :report_cards, -> (student) { ... } 
+0

。 – Mike

+0

いいえ、そうではありません。 Just Active Recordの魔法。 – Oleg

+0

説明してください。これは私の質問には答えません。 student.report_cardsを参照するたびに、パラメータの数が一致しなくなるため例外がスローされます。 – Mike

1

ラムダにパラメータとしてスコープをHAS_MANYするオブジェクトを渡すことができます:私は、ユーザーに関連付けられているモデルを持っているところ、私は私のプロジェクトでこれを使用しています

class Student < ActiveRecord::Base 
    has_many :report_cards, ->{ where(graded: true).order(:semester_number).presence || unscoped.order(:semester_number) } 
end 
+0

':: Base'を忘れました – trushkevich

0

ユーザーモデルでは、only_deletedのスコープを作成し、削除されました。

関連する問題