Though there is nothing strictly wrong with your proposed design, I would say be wary of the additional data and behaviour that can be tied to students, teachers, and parents.
What you want to avoid is:
class Profile
def general_method
if profile_type == 'student'
# do this
elsif profile_type == 'parent'
# do this
elseif profile_type == 'teacher'
# do this
end
end
end
One way of resolving this would be single table inheritance, but that would only resolve the behavioural pollution. The data would still be in the same table, which can develop into a messy schema as your models grow apart in structure and behaviour.
There is nothing wrong with jumping to something else AFTER that happens, but you could spend a little more time designing upfront to avoid it.
It comes down to do you want a messy database or a messy object model? Are a few redundant columns that bad? For example, having teacher's salary and student's allowance in the same table? The alternative is separating the table, but then you have duplicate columns on each table such as first/last name, address.
As you talk it through like this you begin to understand that it probably IS worth having a few potentially redundant columns in the table just to avoid those duplicate columns on multiple tables. Having said that, DB design is not my day-job, so keep looking around and see what works for you!
Aside from the design, let's talk a little about the code itself.
def get_student_classes
student_profile = profiles.select { |p| p.profile_type == 'student' }.first
return [] if student_profile.nil?
return klasses.select { |k| k.profile_id == student_profile.id }
end
First problem is you have named your method get_student_classes
. In Ruby we would simply call this student_classes
. Forget getter and setter naming conventions. You get by calling the method itself, you set by assigning (student_classes = etc
).
Second problem above is that you've used select
. This will fetch all records from the database and then loop over them. Sure, it doesn't matter when there are only 10 or so records, but it becomes much less efficient as the data piles up. To prevent that, use a query. On top of that, use a scope to build that query.
The third problem is that you are performing two queries to get what you want (klasses.select
).
What you want to do is run a single query to get the classes you want without the need to loop over and filter them in Ruby.
Hate to hit you with an anti-climax but I've run out of steam tonight :) I would advise you perhaps post it on SO. There is surely a better way of querying for that data.