I’ve been wrestling with database normalization and the “Rails Way” and I wanted to get peoples opinions as to if there’s a best practices guide to how to do it. Here’s some background:
Let’s assume we have a model/schema similar to the following:
class Student < ActiveRecord::Base
has_many :exams, through: :student exams
class StudentExam < ActiveRecord::Base
class Exam < ActiveRecord::Base
has_one :college, through: :professor
class Question < ActiveRecord::Base
class Response < ActiveRecord::Base
The idea is that a Professor creates an Exam andQuestions, and then assigns students through StudentExam to take that exam. The students then generate Responses to the exam questions, and then those Responses are graded by Evaluations done by the Professor.
Now, given the above background, I wanted to ask a few questions to get peoples opinions on how to structure this app:
- In general, are there any changes you guys would make with the given associations?
- For the Response model, does it make sense to do “belongs_to :student”, or should it instead be “belongs_to :student_exam”? It feels more logical to have the former, because we can get the exam through the question if need be (response.question.exam), and its really a student responding to it, not a student_exam. But if we used student_exam, we could use response.student_exam.exam to get back to the exam, and response.student_exam.student to get back to the student.
- If we were on an Evaluation and we wanted to back to a exam, it would seem quite cumbersome to do evaluation.response.question.exam just to get back to the exam.
- Now we could always create a method on the model that just shortened it for us, but is there a point when you are chaining associations that somewhere along the line you add in another foreign_key to a table for easy lookup?
- If we wanted to see all Evaluations for an Exam, what would be the best way to do that?
- Only way I could see to do it easily would be to break it up, something like:
- @questions = @exam.questions
- @responses = Response.where(question_id: @questions.pluck(:id)
- @evaluations = Evaluation.where(response_id: @responses.pluck(:id)
- This seems kind of painful
Let me know your thoughts – or if you have any great books on the best strategies for normalizing/denormalizing within or without the scope of a rails app, I’d love to hear them.