从用户帖子的upvotes / downvotes计算业力

时间:2013-10-07 05:07:00

标签: ruby-on-rails

我有一个用户和帖子模型,我正在使用acts_as_votable gem(它给我一个'投票'表)来upvote / downvote帖子。我想为每个用户分配业力,其中业力是用户从他/她的所有帖子中获得的upvotes数量减去downvotes的总数。

目前我在用户模型上有这个实例方法来计算业力:

  def karma
    count = 0
    self.posts.each do |post|
      count += post.upvotes.size - post.downvotes.size
    end
    return count
  end

我不认为上面的O(2n)运行时非常有效,因为每个帖子都需要两个额外的数据库查询,一个用于upvotes,一个用于downvotes。

关于如何将上述内容组合到单个查询中,或以其他方式提高效率的任何想法?

1 个答案:

答案 0 :(得分:1)

不仅关于效率,这种设计在OOP方面也不好。用户模型考虑的范围超出了其范围。 Karma是属于用户的东西,不应该与其他任何东西捆绑在一起。

更好的方法是将“Karma”与Post分开。

# Add a "karma" column
$ rails g migration AddKarmaToUser

# Or use a dedicated table
class User < ActiveRecord::Base
  has_one :karma

然后,使用Controller或服务对象来改变业力。为简单起见,我将在这里介绍Controller。不要使用模型回调,因为它是交叉模型。

class PostsController < ApplicationController
  def upvote
    post = Post.find(params[:id])
    post.upvote # pseudo API of acts_as_votable
    current_user.increase_karma
  end

  def downvote
    # ...
    current_user.decrease_karma
  end
end

# Model
class User < ActiveRecord::Base
  attr_accessible :karma

  def increase_karma(count=1)
    update_attribute(:karma, karma + count)
  end

  def descrease_karma(count=1)
    # ...
  end
end

# View
user.karma