【问题标题】:Cleaning up controllers to speed up application清理控制器以加快应用程序
【发布时间】:2011-05-21 19:05:12
【问题描述】:

所以在我的应用中,我有通知和不同的记录计数,它们用于整体布局,因此在每个页面上都需要。

目前在我的 application_controller 中有很多类似的东西:

@status_al = Status.find_by_name("Alive")
@status_de = Status.find_by_name("Dead")
@status_sus = Status.find_by_name("Suspended")
@status_hid = Status.find_by_name("Hidden")
@status_arc = Status.find_by_name("Archived")
@balloon_active = Post.where(:user_id => current_user.id, :status_id => @status_al.id )
@balloon_dependent = Post.where(:user_id => current_user.id, :status_id => @status_de.id )
@balloon_upcoming = Post.where(:user_id => current_user.id, :status_id => @status_sus.id )
@balloon_deferred = Post.where(:user_id => current_user.id, :status_id => @status_hid.id )
@balloon_complete = Post.where(:user_id => current_user.id, :status_id => @status_arc.id )

.. 那真的只是一小部分,我有类似的电话至少加倍。问题是我几乎在每一页上都需要这些数字,但我觉得我在这里重复了太多次 DB wayyyy。

有更好的实现方法吗?

【问题讨论】:

  • 如果他们解决了您的问题,如果您能接受我们的答案之一,那就太好了。谢谢! :)
  • 很抱歉,仍在实施更改 - 答案已接受!

标签: ruby-on-rails ruby ruby-on-rails-3 controller


【解决方案1】:

范围

首先,您应该将其中的许多移动到scopes,这将使您能够以更灵活的方式使用它们,例如使用 ActiveRecord 链接查询。见http://edgerails.info/articles/what-s-new-in-edge-rails/2010/02/23/the-skinny-on-scopes-formerly-named-scope/index.html

索引

其次,如果您仍然要执行所有这些查询,请确保您索引您的数据库,例如,通过名称快速找到Status。完成第一个索引的示例迁移:

add_index :status (or the name of your Status controller), :name

会话

如果您在此处需要的数据并不重要,即您不需要依赖它来进行进一步的计算或数据库更新,您可以考虑将其中的一些数据存储在用户会话中。如果你这样做,你可以简单地在未来从会话中读取你需要的任何内容,而不是在每次页面加载时都访问你的数据库。

如果此数据很重要和/或必须更新到第二个,请避免使用此选项。

计数器缓存

如果您需要定期进行某些记录计数,请考虑设置counter_cache。基本上,在您的模型中,您执行以下操作:

Parent.rb
has_many :children

Child.rb
belongs_to :parent, :counter_cache => true

确保您的parent 表有一个名为child_count 的字段,Rails 会在每个孩子的创建/删除时为您更新该字段。如果您使用 counter_caching,您将避免访问数据库来获取计数。

注意:使用 counter_caching 会导致稍微更长的创建和销毁操作,但如果您经常使用这些计数,通常值得使用 counter_cache。

【讨论】:

    【解决方案2】:

    您应该只需要 1 个数据库查询,例如:

    @posts = Post.where(:user_id => current_user.id).includes(:status)
    

    然后使用 Enumerable#group_by 将帖子收集到不同的类别中:

    posts_by_status = @posts.group_by do {|post| post.status.name }
    

    这会给你一个哈希:

    {'Alive' => [...], 'Dead' => [...]}
    

    等等

    【讨论】:

    • 您说得对,在每次页面查看时只需要一个查询即可解决 OP 的问题,但 OP 还试图避免在用户每次选择页面上的任何页面时重复此查询地点。为了在 DB 上实现极致轻盈,OP 需要研究缓存和/或使用会话。
    • 好点。 OP 应该阅读 Rails 中可用的各种形式的缓存:guides.rubyonrails.org/caching_with_rails.html
    • 嘿,安迪,我不确定我是否了解如何在这里使用 group_by?如何指定分组依据的状态类型?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多