ruby-on-rails – 如何让Rails加载计数?

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 如何让Rails加载计数?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这与 a year and change ago的问题有关.

我提出了一个应该开箱即用的问题的例子,只要你有sqlite3可用:https://github.com/cairo140/rails-eager-loading-counts-demo

安装说明(主分支)

git clone git://github.com/cairo140/rails-eager-loading-counts-demo.git
cd rails-eager-loading-counts-demo
rails s

我在存储库中有更全面的写作,但我的一般问题是这样.

如何使Rails能够以最大限度地减少数据库查询的方式使用Rager的加载计数?

尽管在ActiveRelation中通过#includes(:associated)包含了该关联,但在使用#count关联时,n 1问题就会出现.解决方法是使用#length,但是只有当被调用的对象已经被加载时,这样才能很好地工作,更不用说我怀疑它与Rails内部已经做的事情重复了.此外,使用#length的问题是,当关联未加载开始并且计数是所有您需要的时候,它会导致不幸的过载.

从自述:

We can dodge this issue by running #length on the posts array (see appendix),which is already loaded,but it would be nice to have count readily available as well. Not only is it more consistent; it provides a path of access that doesn’t necessarily require posts to be loaded. For instance,if you have a partial that displays the count no matter what,but half the time,the partial is called with posts loaded and half the time without,you are faced with the following scenario:

  • Using #count
    • n COUNT style queries when posts are already loaded
    • n COUNT style queries when posts are not already loaded
  • Using #length
    • Zero additional queries when posts are already loaded
    • n * style queries when posts are not already loaded

Between these two choices,there is no dominant option. But it would be nice to revise #count to defer to #length or access the length that is some other way stored behind the scenes so that we can have the following scenario:

  • Using revised #count
    • Zero additional queries when posts are already loaded
    • n COUNT style queries when posts are not already loaded

那么这里有什么正确的方法呢?有没有我忽视的东西(很可能)?

解决方法

看来,实现这种设施的最佳方式可能是为您想要的独立模型和子计数对象创建sql视图(参考: herehere)及其相关的ActiveRecord模型.

您可以非常聪明地使用原始模型与set_table_name结合使用子类:sql_view_name来保留对象上的所有原始方法,甚至可能还包含其中一些关联.

例如,我们要在你的例子中添加“Post.has_many:comments”,就像在@ Zubin的上面的答案一样;那么人们可能会做到:

class CreatePostsWithCommentsCountsView < ActiveRecord::Migration
      def self.up
        #Create sql View called posts_with_comments_counts which maps over 
        # select posts.*,count(comments.id) as comments_count from posts 
        #   left outer join comments on comments.post_id = posts.id 
        #   group by posts.id
        # (As zubin pointed out above.) 
        #*Except* this is in sql so perhaps we'll be able to do further 
        # reducing queries against it *as though it were any other table.*
      end    
   end

   class PostWithCommentsCount < Post         #Here there be cleverness.
                                              #The class definition sets up PWCC 
                                              # with all the regular methods of 
                                              # Post (pointing to the posts table
                                              # due to Rails' STI facility.)

    set_table_name :posts_with_comment_counts #But then we point it to the 
                                              # sql view instead.
                                              #If you don't really care about
                                              # the methods of Post being in PWCC
                                              # then you could just make it a 
                                              # normal subclass of AR::Base.
   end

   PostWithCommentsCount.all(:include => :user)  #ObvIoUsly,this sort of "upward
     # looking" include is best used in big lists like "latest posts" rather than
     # "These posts for this user." But hopefully it illustrates the improved 
     # activerecordiness of this style of solution.
   PostWithCommentsCount.all(:include => :comments) #And I'm pretty sure you 
     # should be able to do this without issue as well. And it _should_ only be 
     # the two queries.
原文链接:https://www.f2er.com/ruby/271558.html

猜你在找的Ruby相关文章