どこで間違っているのかもわからない

 今更いちいち書くようなことでは無いような気もするが、データベース設計は難しい。今は、以下のような問題設定の元で悩んでいる。

  • ユーザはレポートを書く(レポートはユーザに所属する)
  • レポートにはどの問題に対するレポートであるのかという属性がある
  • ユーザはあるひとつのグループに所属する
  • グループで提出するレポートは、グループ内の誰かが提出すれば良い
  • グループ課題であるかどうかは問題の属性として付与されている

 とすると、あるグループに所属する人間が出したグループ課題の一覧を求めるときに、どうすれば良いか。

Report.find_by_group_and_report_type(params[:group_id], :group_report)

 で求めたいのだけれど、レポートはgroup idを持ってないので、この形ではfindできない。
 別の案としては、Groupにhas_many reports :through usersという属性を付けて、group.reportsとする、というものがあるが、これには以下のような問題点がある。

  • なぜか動かない(どっかコードが間違ってるっぽい)
  • グループ課題以外のレポートも一緒に取れてしまうので、それを後で取り除く必要がある。

 前者はまぁ頑張るとして、後者は非常に嫌だ。そもそも、グループがレポートを所有する、というのは、なんだか慣れない感じがする。抽象的なモデルがなにかを所有する、というところに違和感を感じるのかしら。
 さらに他の案としては、モデルのレベルでReportとGroupReportを分離してしまう、というものがある。これは単純にやってしまうとコードの重複が増えてしまってキモい事になるが、継承とかうまく使えば、うまいこといけるかもしれない。しかし、もう既にデータはReportとして提出されてしまっているので、それを今更ReportとGroupReportに分類するのは面倒だ。今回はこれは避けたい。(まぁ、データを移行するコードを書けばいいんだけども…。)あと、Controllerは単純に継承してしまっても大丈夫なんじゃないかと思うんだけど、Modelは単純に継承できるものなのかどうか、ちょっとわからない。
 今のところ、グループに所属する全員のuser_idを求めて、その人数分だけReport.find_by_report_typeの結果をcollectしている。1グループに所属する人数はせいぜい10人やそこらなので、パフォーマンス的には問題にはならないようだ。
 結局、問題は、きっともっと良い解法があるだろうに、それがわからないという事だ。きっと、本を読めば書いてあるんだろうけど。
 (追記):joinsを使えば良さそうな感じ。とりあえず後で試す。