如何使用 ActiveRecord 按作者的书数对作者进行排序? [英] How to sort authors by their book count with ActiveRecord?

查看:25
本文介绍了如何使用 ActiveRecord 按作者的书数对作者进行排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有 Book 模型和 Author 模型.我想列出所有按书数排序的作者.最好的方法是什么?

Let's say I have Book model and an Author model. I want to list all authors sorted by their book count. What's the best way to do that?

我知道如何在 SQL 中执行此操作,方法是使用嵌套选择或某些连接执行 where .. in.但我想知道的是如何使用 ActiveRecord 很好地做到这一点.

I know how to do this in SQL, either by doing where .. in with a nested select or with some join. But what I'd like to know is how to do this nicely with ActiveRecord.

推荐答案

正如 Kevin 所建议的,counter_cache 是最简单的选项,我绝对会使用.

As Kevin has suggested, counter_cache is the easiest option, definitely what I would use.

class Author < ActiveRecord::Base
  has_many :books, :counter_cache => true
end

class Book < ActiveRecord::Base
  belongs_to :author
end

如果您使用的是 Rails 2.3 并且您希望这是默认顺序,您可以使用新的 default_scope 方法:

And if you are using Rails 2.3 and you would like this to be the default ordering you could use the new default_scope method:

class Author < ActiveRecord::Base
  has_many :books, :counter_cache => true

  default_scope :order => "books_count DESC"
end

books_count 是执行计数器缓存行为的字段,可能有比在默认范围内直接使用它更好的方法,但它为您提供了想法并完成了工作.

books_count is the field that performs the counter caching behaviour, and there is probably a better way than using it directly in the default scope, but it gives you the idea and will get the job done.

如果非 Rails 应用程序更改数据,则询问 counter_cache 是否可以工作,这是响应评论,它可以,但不是默认方式,因为 Rails 在保存时递增和递减计数器.您可以做的是在 after_save 回调中编写自己的实现.

In response to the comment asking if counter_cache will work if a non rails app alters the data, well it can, but not in the default way as Rails increments and decrements the counter at save time. What you could do is write your own implementation in an after_save callback.

class Author < ActiveRecord::Base
  has_many :books

  after_save :update_counter_cache

  private
    def update_counter_cache
      update_attribute(:books_count, self.books.length) unless self.books.length == self.books_count
    end
end

现在您没有安装 counter_cache,但是如果您按照 counter_cache 约定命名数据库 books_count 中的字段,那么当您查找时:

Now you don't have a counter_cache installed, but if you name the field in the database books_count as per the counter_cache convention then when you look up:

@Author = Author.find(1)
puts @author.books.size

它仍然会使用计数器缓存的数字,而不是执行数据库查找.当然,这仅在 rails 应用程序更新表格时才有效,因此如果另一个应用程序执行某些操作,那么您的数字可能会不同步,直到 rails 应用程序返回并必须保存.我能想到的唯一解决方法是,如果您的 Rails 应用程序没有足够频繁地进行查找以使其无关紧要,则使用 cron 作业来同步数字.

It will still use the counter cached number instead of performing a database lookup. Of course this will only work when the rails app updates the table, so if another app does something then your numbers may be out of sync until the rails application comes back an has to save. The only way around this that I can think of is a cron job to sync numbers if your rails app doesn't do lookup up things often enough to make it not matter.

这篇关于如何使用 ActiveRecord 按作者的书数对作者进行排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆