Как отсортировать авторов по их книжному количеству с ActiveRecord?

Попробуйте непрозрачность:

opacity:0.4;
filter:alpha(opacity=40); /* For IE8 and earlier */
6
задан Sijmen Mulder 5 June 2009 в 23:28
поделиться

3 ответа

Как предложил Кевин, counter_cache - самый простой вариант, который я определенно использовал бы.

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

class Book < ActiveRecord::Base
  belongs_to :author
end

И если вы используете Rails 2.3 и хотите, чтобы это был порядок по умолчанию, вы можете использовать новый метод default_scope:

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

  default_scope :order => "books_count DESC"
end

books_count - это поле, которое выполняет кэширование счетчика, и, вероятно, есть способ лучше, чем используя его непосредственно в области действия по умолчанию, но он дает вам идею и выполнит работу.

EDIT:

В ответ на комментарий, спрашивающий, будет ли counter_cache работать, если приложение без рельсов изменяет данные, ну, это жестяная банка, но не по умолчанию, поскольку Rails увеличивает и уменьшает счетчик во время сохранения. Что вы могли бы сделать, так это написать свою собственную реализацию в обратном вызове after_save.

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, но если вы назовете поле в базе данных books_count в соответствии с соглашением counter_cache, тогда, когда вы посмотрите вверх:

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

Он по-прежнему будет использовать кэшированное число счетчика вместо выполнения поиска в базе данных. Конечно, это будет работать только тогда, когда приложение rails обновляет таблицу, поэтому, если другое приложение что-то делает, ваши числа могут быть не синхронизированными, пока приложение rails не вернется и его не придется сохранять. Единственный способ обойти это, что я могу придумать, - это задание cron для синхронизации чисел, если ваше приложение rails не выполняет поиск вещей достаточно часто, чтобы это не имело значения.

Что вы могли бы сделать, так это написать свою собственную реализацию в обратном вызове after_save.

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, но если вы назовете поле в базе данных books_count в соответствии с соглашением counter_cache, тогда, когда вы посмотрите вверх:

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

Он по-прежнему будет использовать кэшированное число счетчика вместо выполнения поиска в базе данных. Конечно, это будет работать только тогда, когда приложение rails обновляет таблицу, поэтому, если другое приложение что-то делает, ваши числа могут быть не синхронизированными, пока приложение rails не вернется и его не придется сохранять. Единственный способ обойти это, что я могу придумать, - это задание cron для синхронизации чисел, если ваше приложение rails не выполняет поиск вещей достаточно часто, чтобы это не имело значения.

Что вы могли бы сделать, так это написать свою собственную реализацию в обратном вызове after_save.

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, но если вы назовете поле в базе данных books_count в соответствии с соглашением counter_cache, тогда, когда вы посмотрите вверх:

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

Он по-прежнему будет использовать кэшированное число счетчика вместо выполнения поиска в базе данных. Конечно, это будет работать только тогда, когда приложение rails обновляет таблицу, поэтому, если другое приложение что-то делает, ваши числа могут быть не синхронизированными, пока приложение rails не вернется и его не придется сохранять. Единственный способ обойти это, что я могу придумать, - это задание cron для синхронизации чисел, если ваше приложение rails не выполняет поиск вещей достаточно часто, чтобы это не имело значения.

но если вы назовете поле в базе данных books_count в соответствии с соглашением counter_cache, тогда, когда вы посмотрите:

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

Он все равно будет использовать кэшированный счетчик номер вместо выполнения поиска в базе данных. Конечно, это будет работать только тогда, когда приложение rails обновляет таблицу, поэтому, если другое приложение что-то делает, ваши числа могут быть не синхронизированными, пока приложение rails не вернется и его не придется сохранять. Единственный способ обойти это, что я могу придумать, - это задание cron для синхронизации чисел, если ваше приложение rails не выполняет поиск вещей достаточно часто, чтобы это не имело значения.

но если вы назовете поле в базе данных books_count в соответствии с соглашением counter_cache, тогда, когда вы посмотрите:

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

Он все равно будет использовать кэшированный счетчик номер вместо выполнения поиска в базе данных. Конечно, это будет работать только тогда, когда приложение rails обновляет таблицу, поэтому, если другое приложение что-то делает, ваши числа могут быть не синхронизированными, пока приложение rails не вернется и его не придется сохранять. Единственный способ обойти это, что я могу придумать, - это задание cron для синхронизации чисел, если ваше приложение rails не выполняет поиск вещей достаточно часто, чтобы это не имело значения.

поэтому, если другое приложение что-то делает, ваши числа могут быть не синхронизированы, пока приложение rails не вернется и не будет сохранено. Единственный способ обойти это, что я могу придумать, - это задание cron для синхронизации чисел, если ваше приложение rails не выполняет поиск вещей достаточно часто, чтобы это не имело значения.

поэтому, если другое приложение что-то делает, ваши числа могут быть не синхронизированы, пока приложение rails не вернется и не будет сохранено. Единственный способ обойти это, что я могу придумать, - это задание cron для синхронизации чисел, если ваше приложение rails не выполняет поиск вещей достаточно часто, чтобы это не имело значения.

9
ответ дан 8 December 2019 в 03:40
поделиться

Я предлагаю счетчик кэшировать счетчик книг в качестве другого атрибута в Author (Rails поддерживает это с опцией для ассоциации). Это, безусловно, самый быстрый метод, и Rails очень хорошо умеет синхронизировать счетчик.

7
ответ дан 8 December 2019 в 03:40
поделиться

Взято из http://www.ruby-forum.com/topic/164155

Book.find(:all, :select => "author_id, count(id) as book_count", :group => "author_id", :order => "book_count")
9
ответ дан 8 December 2019 в 03:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: