2017-07-22 13 views
2

ここに私が持っている関連があります。関連レコードが存在しない親レコードを見つけよう

award_test.rb

has_many :instructor_student_awards , :dependent => :destroy 
has_many :award_test_payment_notifications, dependent: :destroy 

instructor_student.rb

has_many :instructor_student_awards, :dependent => :destroy 
has_many :awards, through: :instructor_student_awards 
has_many :award_test_payment_notifications, dependent: :destroy 

belongs_to :award 
belongs_to :instructor_student 
belongs_to :award_test 
instructor_student_award.rb

"award_tests" 
    t.date  "test_date" 
    t.time  "test_time" 
    t.integer "award_id" 
    t.decimal "test_fee" 


"award_test_payment_notifications" 
    t.text  "response_params" 
    t.string "status" 
    t.string "transaction_id" 
    t.string "paid_by" 
    t.float "amount" 
    t.string "merchant_reference" 
    t.integer "award_test_id" 
    t.integer "instructor_student_id" 

"instructor_student_awards" 
    t.integer "instructor_student_id" 
    t.integer "award_test_id" 
    t.boolean "is_registered",   default: false 

schema.rb

belongs_to :award_test 
belongs_to :instructor_student 

award_test_payment_notification.rbどれインストラクターの生徒が表彰テストに登録することができます。 1人のインストラクターの生徒が複数の賞のテストに登録することができます。受験生は受験者は受験料を支払う必要があります。インストラクターの生徒は2種類の方法で賞品テストを受けることができます。

  1. オンライン

  2. 現金

インストラクターの学生がその賞のテストのために支払います。インストラクターの学生とaward_testのデータはaward_test_payment_notificationsに挿入されます。 award_test_notificationsテーブルには、学生および賞のテストに関連するすべてのフィールドがあります。

講師の生徒がその授業料を支払わなかった場合、授業料が支払われない場合、授業料支払い通知は、その授業料試験の場合に限りその条件にはなりません。

インストラクター学生1は、10,11,12のような3つの賞のテストに登録します。

インストラクターの学生1は、賞のテスト10

インストラクターの学生1は、賞のテスト11のために支払われていなかった賞のテストのためのオンライン支払ったインストラクターの学生1のための現金を支払いました。

したがって、インストラクター学生は、2つの賞テスト支払い通知を持っています 1)賞品テスト10 2)a病棟テスト12

私は2017年7月31日に2017年1月1日の間賞・テストを検索し、この3つの賞はインストラクターの学生1よりも、このフィルタ 内に属している3つのカテゴリーのリターンとなります。

  1. 現金支払い

  2. オンライン決済

  3. 未払い

私は2日を持っていると私は2つの日付に基づいてデータをフィルタリングする必要があります。その日付はテスト日になります。私はすべての現金支払い、オンライン支払い、未払い金を区別しなければなりません。

ここで私は現金支払いとオンライン支払いを得るために何をしましたか?

current_admin_award_test = AwardTest.joins(instructor_student_awards: {:instructor_student => :award_test_payment_notifications}).where("test_date <= ? AND test_date >= ? AND instructor_student_awards.instructor_student_id IN (?) ", @endMonth.end_of_month, @startMonth.beginning_of_month, @all_instructor_student_ids) 

@award_test_cash = current_admin_award_test.joins("INNER JOIN award_test_payment_notifications atn ON award_test_payment_notifications.award_test_id = award_tests.id").where("award_test_payment_notifications.paid_by = ? ","Cash").select("DISTINCT(award_tests.id), instructor_student_awards.instructor_student_id, award_test_payment_notifications.paid_by, award_tests.test_fee, award_tests.test_date") 

@award_test_paid_online = current_admin_award_test.joins("INNER JOIN award_test_payment_notifications atn ON award_test_payment_notifications.award_test_id = award_tests.id").where("award_test_payment_notifications.paid_by <> ? ","Cash").select("DISTINCT(award_tests.id), instructor_student_awards.instructor_student_id, award_test_payment_notifications.paid_by, award_tests.test_fee, award_tests.test_date") 

正常です。しかし、私はどのように1人のインストラクターの学生の複数の賞のテストのための無償の賞のテストのリストを取得するつもりです。

アップデート1

InstructorStudentAwardの役割は何ですか?

受講者が受験者に受験したとき。データは インストラクターの学生賞に記録されています。

そのAwardTestに支払いが記録されている場合、そのイベントは であるとみなされます。 OK?

はい。インストラクターの学生が賞を受賞した時。賞品テストのお支払い 金額に関係なく通知が記録されます。

AwardTestに登録するInstructorStudentごとにInstructorStudentAwardの関連付けが作成されていますか?

はい、あなたは正しいです。

だから、あなたが欲しいのはどのInstructorStudentAwardがAwardTestが関連 AwardTestPaymentNotification

はい

は、私はあなたが、PostgreSQLデータベース

を使用していると仮定することはできますが欠落している InstructorStudentペアのJOIN、JOIN、あるはい、I PostgreSQLデータベースを使用しています。

答えて

0

私はあなたの連想構造を複製するために、あなたの私は必要な質問(とあなたが言及しなかったいくつかのこと)の一部で、このgithubのレポを追加しました。プロジェクトのルートで

https://github.com/kingdonb/ashvin-stackoverflow-post

example.rb私が想像Railsのランナースクリプトは、これらのものを作成し、一緒にリンクされているか、ほぼ複製されます。

あなたのクエリは、ビットのリードであることを再フォーマット:あなたはそれを行うためのものならば、それは黙って参加インナーをやっているので、

current_admin_award_test = AwardTest.joins(
    instructor_student_awards: { 
    :instructor_student => :award_test_payment_notifications 
    }).where("test_date <= ? AND test_date >= ? 
    AND instructor_student_awards.instructor_student_id 
    IN (?) ", 
    @endMonth.end_of_month, 
    @startMonth.beginning_of_month, @all_instructor_student_ids) 

@award_test_cash = current_admin_award_test.joins(
    "INNER JOIN award_test_payment_notifications atn ON 
    award_test_payment_notifications.award_test_id = 
    award_tests.id"). 
    where(
    "award_test_payment_notifications.paid_by = ? ", "Cash" 
).select(
    "DISTINCT(award_tests.id), 
    instructor_student_awards.instructor_student_id, 
    award_test_payment_notifications.paid_by, 
    award_tests.test_fee, award_tests.test_date") 

@award_test_paid_online = current_admin_award_test.joins(
    "INNER JOIN award_test_payment_notifications atn ON 
    award_test_payment_notifications.award_test_id = 
    award_tests.id"). 
    where(
    "award_test_payment_notifications.paid_by <> ? ","Cash" 
).select(
    "DISTINCT(award_tests.id), 
    instructor_student_awards.instructor_student_id, 
    award_test_payment_notifications.paid_by, 
    award_tests.test_fee, award_tests.test_date") 

私が思う行方不明のクエリは、、current_admin_award_testから派生させることはできません。あなたがいない追加のコンテキストで「参加する」と言うとき、Railsはあなたが内部結合を意味することを推測する:この結果でhttps://apidock.com/rails/ActiveRecord/QueryMethods/joins#docs_body

ルック:

current_admin_award_test = AwardTest.joins(
    instructor_student_awards: { 
    :instructor_student => :award_test_payment_notifications 
    }) 

あなたが戻っのみ支払わInstructorStudentAwardsを入手します!

Inner Joinが行結果を生成するために両側で一致する必要があるため、AwardTestPaymentNotificationsと一致しないレコードを削除します。したがって、その関連オブジェクトからクエリを開始すると、未払いのレコードは返されません。

あなたが欲しい:

@award_test_unpaid = AwardTest.left_outer_joins(
    instructor_student_awards: { 
    instructor_student: :award_test_payment_notifications 
    }).where(award_test_payment_notifications: { id: nil }). 

[ and the rest of your criteria from current_admin_award_test ] 

    where("test_date <= ? AND test_date >= ? 
    AND instructor_student_awards.instructor_student_id 
    IN (?) ", 
    @endMonth.end_of_month, 
    @startMonth.beginning_of_month, @all_instructor_student_ids) 

あなたがRailsの以前のバージョンを使用している場合#left_outer_joinsだけのRails 5.0で追加されたので、それはより複雑になります。

これを改善したい場合は、award_test_payment_notificationsに参加していないパラメータ化されたスコープにcurrent_admin_award_testを作成することができます(すでに派生した支払いステータスリストを作成するためにそのテーブルに参加しています。なぜあなたはDISTINCTを使うことに頼らざるを得なかったのですか?または別の理由がありましたか?)

多分彼らは1つのAwardTestに対して複数のAwardTestPaymentNotificationsを持っていて、それから重複したAwardTestレコードを取り戻すことはしませんでした。 OK。この新しい範囲を@award_test_unpaidの基礎として使用することもできます。

scope :current_admin_award_test, ->(
    end_date, begin_date, instructor_student_list) { 
    joins(instructor_student_awards: :instructor_student). 
    where("test_date <= ? AND test_date >= ?", 
     end_date.end_of_month, begin_date.beginning_of_month). 
    where(instructor_student_awards: 
     { instructor_student: instructor_student_list } 
    ) 
    } 

(GitHubのプロジェクトでin context)私はそれがAwardTestモデルに進みコミットでこれを置きます。

あなたの3つのプライベート変数も同じパラメータを持つスコープとすることが可能(日付・ロジックを処理し、このマスタースコープ、それらを通過する。)

(疑いの利益を与えるの中で、あなたはこれらを持っているかもしれませんあなたのモデルのものはすでにありますが、あなたがそれにあまりにも多くのコードを入れたくないので質問に単に含まれていませんでした)

InstructorStudentが彼の請求書の1つを支払っていない場合、このリストに表示されます。すべての請求書が払われれば、このリストにはInstructorStudentは表示されません。私はあなたが達成しようとしていたものだと思いますか?

あなたはそれらを一つ一つ強く文言のメールを送ることができますので、さらに、未払いの請求書を持っているInstructorStudentレコードのリストを導出したい場合は、ここではちょうどこのような次のようになります、ボーナスについて

@award_test_unpaid. 
    map(&:instructor_student_awards).flatten. 
    map(&:instructor_student). 
    map(&:id).uniq 

私はちょうどあなたが望むものを行うcurrent_unpaidスコープがあるように、私は立ち上がったレポにいくつかの時間を費やして、レール協会とスコープを取り除きました。

scope :current_unpaid, ->(
    end_date, begin_date, instructor_student_list) { 
    current_admin_award_test(end_date, begin_date, instructor_student_list). 
    left_outer_joins(:award_test_payment_notifications). 
     where(award_test_payment_notifications: { id: nil }) 
    } 

2017年8月4日編集:@ashvinが、彼はそれがRailsの5まで添加しなかったので、そう.left_outer_joinが動作しません...この生のSQLがで動作しますが、Railsの4.1にあった明らかにしましたしかしその場所、:そして、

scope :current_unpaid, ->(
    end_date, begin_date, instructor_student_list) { 
    current_admin_award_test(end_date, begin_date, instructor_student_list). 
    joins("LEFT JOIN award_test_payment_notifications 
      ON award_tests.id = 
       award_test_payment_notifications.award_test_id 
      AND instructor_students.id = 
       award_test_payment_notifications.instructor_student_id"). 
     where(award_test_payment_notifications: { id: nil }) 
    } 

することができます

AwardTest.current_unpaid(Date.today, Date.today, InstructorStudent.all.map(&:id)) 

、今月のすべての未払いのAwardTestのリストを入手してください!

AwardTestモデルのhas_many :award_test_payment_notificationsに依存します。これは、上記で定義したcurrent_admin_award_testの範囲にもよります。その作業を行うためのすべての変更は、このコミットにあります:more time on rails associations。お役に立てれば!

+1

はい。私は自分の質問を更新し、あなたの質問に答えました。 :) – ashvin

+0

@ashvin私はPure Railsで解決したと思う。うまくいけば、あなたはRails 5.0以上になっているでしょう! – Kingdon

+0

いいえ、レールのバージョンは4.1.1です。 – ashvin

関連する問題