我正在参加Lynda.com课程" Ruby on Rails 4 Essential Training"。它使用创建一个简单的CMS来教授框架。在此CMS中,用户可以创建Subjects
和Pages
。每个Subject
都有许多Pages
。单击链接以查看属于特定主题的页面时,它会将主题ID作为参数传递给Pages controller
。页面控制器然后执行以下操作以确定要显示的页面:
@subject = Subject.find(params[:subject_id])
@pages = @subject.pages
这很简单,很有意义,并且可以产生非常易理解的代码。但是,通过首先加载Subject
然后查找其页面,它会产生额外的数据库调用。在控制台中我看到:
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
在我看来,更有效的方法是编写类似的东西:
@pages = Page.where(subject_id: params[:subject_id])
实际上,当我这样做时,我只看到一个SQL查询。使用第一种方法是否被认为是最佳做法,尽管它会导致2次查询?或者这只是用于学习目的,最终我的方法会被认为是两者中的更好?
答案 0 :(得分:1)
首先取决于您是否需要@subject和@pages对象。你的提议更高效是对的,现在这可能会或可能不会对你的用户产生真正的影响 - 你需要进行性能分析才能确定。
最后,可以对教程代码稍作修改,使其成为使用' includes':
的高效工具。@subject = Subject.includes(:pages).find(params[:subject_id])
@pages = @subject.pages
这将使用单个查询加载所有内容。
答案 1 :(得分:0)
如果您不想要@subject或基本上是主题记录,则不需要使用前者,您可以直接使用您在以后的方法中编写的内容访问页面。