控制器指向视图。在该视图中,找到对象<% @XXX = XXXX.where(..... %>
还是那么糟糕?
尝试解决性能问题,这就是我要问的原因。感谢
答案 0 :(得分:3)
在模型中放置查询逻辑更多地与可维护性有关,然后与性能有关。由于大多数ActiveRecord / ARel逻辑处理的轻量级关系对象只触发基于某些方法的实际查询,通常是通过Enumerable(每个/ map / inject / all / first)提供的,通常从视图中调用,实际查询在视图中触发,而不是在其他任何地方触发。
以下是我正在处理atm的应用程序中limit(3)和first(3)之间差异的示例。
ruby-1.9.2-p180 :018 > PressRelease.limit(3).is_a? ActiveRecord::Relation
=> true
ruby-1.9.2-p180 :019 > PressRelease.first(3).is_a? ActiveRecord::Relation
PressRelease Load (2.8ms) SELECT "press_releases".* FROM "press_releases" ORDER BY published_at DESC
=> false
正如您所看到的,限制实际上并不会触发查询,首先是。
在性能方面,您通常会尝试确保在控制器/模型中不执行查询,以便将它们包装在视图中的缓存块中,从而消除大多数请求中的查询。在这种情况下,您确实希望通过调用任何Enumerable方法确保您不在控制器中执行查询。
一个博客的简短示例,其中列出了主页上使用缓存设置的最后10篇博文可能如下所示。
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
# Something like this would trigger the query at this point and should be
# avoided in the controller
# @posts = Post.first(10)
# So @posts here will be the Relation returned from the last_ten scope, not
# an array
@posts = Post.last_ten
end
...
end
# app/models/post.rb
class Post < ActiveRecord::Base
# Will return an ActiveRecord::Relation
scope :last_ten, order('created_at DESC').limit(10)
end
# app/views/posts/index.html.erb
<ul>
# The query will actually trigger within the cache block on the call to each,
# preventing the query from running each time and also reducing the template
# rendering within the cache block.
<%= cache(posts_cache_key) do %>
<% @posts.each do |post| %>
..
<% end %>
<% end %>
</ul>
为清楚起见,所有这些都与做
完全相同# app/views/posts/index.html.erb
<ul>
<%= cache(posts_cache_key) do %>
<% Post.order('created_at DESC').limit(10).each do |post| %>
...
<% end %>
<% end %>
</ul>
除非您现在想要修改它如何提取查询的逻辑,否则您希望添加类似where(:visible => true).where('published_at' <= Time.now)
的内容,跳转到您的视图中,而不是在逻辑应该在模型中进行更改。性能方面,差异是微不足道的,维护方面,后者很快变成了一个小问题。