Reputation: 17573
I'm going through the Lynda.com course "Ruby on Rails 4 Essential Training". It uses the creation of a simple CMS to teach the framework. In this CMS, users can create Subjects
and Pages
. Each Subject
has many Pages
. When clicking a link to view the pages that belong to a particular subject, it passes the subject id as a parameter to the Pages controller
. The pages controller then does the following to determine which pages to show:
@subject = Subject.find(params[:subject_id])
@pages = @subject.pages
This simple, makes sense, and results in very understandable code. However, it results in an extra DB call by first loading the Subject
, and then finding its pages. In the console I see:
Subject Load (0.3ms) SELECT `subjects`.* FROM `subjects` WHERE `subjects`.`id` = 3 LIMIT 1
Page Load (0.3ms) SELECT `pages`.* FROM `pages` WHERE `pages`.`subject_id` = 3 ORDER BY pages.position ASC
It seems to me that the more efficient approach would be to write something like:
@pages = Page.where(subject_id: params[:subject_id])
Indeed, I see only a single SQL query when I do that. Is it considered best practice to use the first approach, despite the fact that it results in 2 queries? Or is that just being used for learning purposes, and ultimately my approach would be considered the better of the two?
Upvotes: 0
Views: 59
Reputation: 7723
It depends first whether you need both the @subject and the @pages object. You are right that your proposal is more performant, now this may or may not make a real difference for your user - you'll need profiling to be sure.
Finally, it is possible to make a slight change to the tutorial code to make it as performant using 'includes':
@subject = Subject.includes(:pages).find(params[:subject_id])
@pages = @subject.pages
This will load everything with a single query.
Upvotes: 1
Reputation: 1034
If you dont want your @subject or basically the subject record, there is not need to use former, you can directly access pages with what you have written in your later approach.
Upvotes: 0