JSBach
JSBach

Reputation: 4747

How to retrieve information that is a join of tables in rails?

My rails app is now working with ActiveRecord and I am really amazed about ruby on rails. My DB has three tables:

Students(Id, name, parentId) Parents(Id, name) Grades(Id, studentId, value)

And the three models.

I have three views, in one of them I have to list the students, so I make a Student.all and it works.

But in one of the views I need to list the student with the parent's name and in the third one I nbeed the student's name and their grades.

I am completely lost now: if my model is my table, how can I retrieve this information which is a join of tables?

Thanks

Edit: I added the line

Student.includes(:parent, :grades).all.each do |student|

And added the relations:

class Student < ActiveRecord::Base
  belongs_to :parent
end

class Parent < ActiveRecord::Base
  has_many :student
end

I had some problems when setting the relations, but now my page loads. Still I can't use the Student.parent.name property. using <%= debug student %> I get the debug info, but no information about the parent. (students.parent shows the parent_id)

Any ideas what I'm missing? It was a name conflict: my Students table had a column called parent. changing to parent_id solved it.

Upvotes: 0

Views: 128

Answers (2)

Steve Rowley
Steve Rowley

Reputation: 1578

You might also be interested in using includes in this case to avoid triggering a query for each student whose grades you retrieve. In this example you would replace:

Student.all.each do |student|

with

Student.includes(:parent, :grades).all.each do |student|

The difference is that in the first case Rails triggers a separate query to retrieve the grades for each student (and a query to get each parent's name). This is often called the "N+1 Problem," since if you have 10 students, to loop through each of them and get their parent's name would take 11 queries (one to get all the students, and one for each of the 10 students to get their parent's name).

When you use includes, Rails eager loads all the associated models and attributes in one query. For more information, check out:

http://guides.rubyonrails.org/active_record_querying.html

Upvotes: 1

zwippie
zwippie

Reputation: 15515

If you have your relations setup correct, you can do something like:

Student.all.each do |student|
  puts student.name
  puts student.parent.name
  student.grades.each do |grade|
    puts grade.value
  end
end

Upvotes: 1

Related Questions