Включение расчетов по связанным данным в запрос ActiveRecord - PullRequest
3 голосов
/ 01 марта 2010

Допустим, у меня есть несколько моделей: User, Post и Vote.У пользователя много постов, а у поста много голосов.Голоса могут быть как за, так и против (сохраняются как логические).То, что я рассматриваю, - это лучший способ сделать такие запросы:

  1. Все пользователи и общее количество полученных голосов за.
  2. Все пользователи и сообщениенабравший наибольшее количество голосов.
  3. Все пользователи и общее количество полученных голосов (как за, так и против).

Существует три способа, которыми я могу думатьДля этого необходимо повысить уровень эффективности:

  1. Рассчитать количество голосов в контроллере, используя циклы.Это может потенциально сделать много дополнительных запросов и данных запросов, которые мне не нужны, например, каждое сообщение и каждая запись голосования.Например (третий запрос):

    @users = User.all
    @vote_count = @users.posts.votes.count # retrieves every post and vote, which I don't need
    
  2. Сохраните подсчет голосов в виде полей в модели пользователя и используйте обратные вызовы для обновления этих подсчетов при каждом голосовании.Это упростит запрос, но я бы хотел, чтобы модели были более слабо связаны, и чтобы схема пользовательской модели не увеличивалась каждый раз, когда мне нужны какие-либо данные по связанной модели.

  3. Используйте какой-то запрос, который будет выполнять эти типы вычислений через SQL и не искать больше данных, чем мне нужно.Это кажется лучшим выбором, но я не знаю, как к нему подойти.Любые предложения / примеры?Спасибо!

1 Ответ

1 голос
/ 01 марта 2010

Используйте плагин vote_fu . Поддерживаются следующие методы:

user.vote_count       # all votes
user.vote_count(true) # votes for
user.vote_count(false) # votes against
posts.votes_count   # all vote count
posts.votes_for     # votes for
posts.votes_against # votes against
posts.votes_total   # votes total

Если вы не хотите использовать плагин, я бы подошел к вашему сценарию следующим образом:

Я предполагаю следующее соотношение между моделями.

class User < ActiveRecord::Base
  has_many :posts
  has_many :votes, :through => :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
  has_many :votes
end

class Vote < ActiveRecord::Base
  belongs_to :post
end

1.1) Для подсчета всех голосов, отданных за всех пользователей

Vote.count  # all
Vote.count(:conditions => {:vote => true}) # all for
Vote.count(:conditions => {:vote => false}) # all against

1.2) Чтобы найти голоса пользователя

user.votes.count # all
user.votes.count(:conditions => {:vote => true}) # all for
user.votes.count(:conditions => {:vote => false}) # all against

2.1) Пользователи с наибольшим количеством голосов «за»

# You can add the limit clause to restrict the rows
User.find(:all, :select => "users.*, count(votes.id) AS count", 
                :joins => [:posts, :votes],  
                :conditions => [" votes.vote = ? ", true],
                :group => "votes.id", :order => "count DESC")

2.2) Сообщения с наибольшим количеством голосов

# You can add the limit clause to restrict the rows
Post.find(:all, :select => "posts.*, count(votes.id) AS count", 
                :joins => [:votes],  
                :conditions => [" votes.vote = ? ", true],
                :group => "votes.id", :order => "count DESC")

3.1) За пользователя общее количество голосов См. 1.2.1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...