这可能是一个菜鸟问题。但我自己无法弄明白。
在我的应用程序中'我正在使用Rails 3.2.8与Mongoid和MongoDB。
我有一个像这样的实例变量:
ProgramsController< ApplicationController中
@program = Program.find(params[:id])
在我的视图文件中,我需要多次使用它。例如;
@program.title
@program.content
@program.schedules (associated with Schedule model)
@program.articles (associated with Article model)
等
问题是,我需要在视图的不同部分使用该实例变量。所以这不像做@program.each do |t| ....
但是当我在视图的不同部分使用@program时,这意味着每次都有一个新的查询......
目前我有31个查询我的观点。不是太多了吗?
那么最佳做法是什么?我应该如何有效地使用实例变量?
提前致谢。
答案 0 :(得分:0)
我对Ruby / Railys并不是特别熟悉,但通常在MVC框架中,控制器会处理数据的提取,因此它只会发生一次。在视图中后续使用它将使用内存中缓存的单个副本来处理请求。在您的视图的一个部分中引用标题,在另一个部分中的内容不应该是性能问题。它们只是缓存对象上的属性访问器。
要验证这一点,您可以计时或模拟请求以查看它是否实际执行了多次(我对此表示怀疑)。
答案 1 :(得分:0)
一旦项目存储在@program
中,它确实保存在那里,后续请求将不会生成查询。如果您只引用@program.title
和@program.content
,那么您可能会没事。您的问题来自协会,例如@program.schedules
和@program.articles
。问题是没有从@program = Program.find(params[:id])
加载计划和文章。这被称为n + 1问题。 {em> Eager Loading 下的official docs州,Eager loaded is supported on all relations with the exception of polymorphic belongs_to associations.
和In order for eager loading to work, the Identity Map must be enabled.
。如果这两个条件都成立,您应该会看到查询减少。如果你不能满足这些要求,一个好的解决方案可能是在控制器中做这样的事情,在一个查询中提前抓取它们:@schedules = Schedule.find_by(program_id: @program.id)
答案 2 :(得分:0)
如果可能,我宁愿使用ActiveRecord。
Rails Official doc说: 您可以使用:include选项指定在使用此关联时应急切加载的二阶关联。
此处时间表和文章是一阶关联。因此,如果您使用ActiveRecord,则不需要它。
官方文件也说:
没有必要使用 :include 进行直接关联 - 也就是说,如果您有 订单belongs_to :客户 ,然后 客户在需要时自动加载。
如果您使用的是ActiveRecord,那么您可能不会打扰这个问题。