我有一个用户和帖子模型,我正在使用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。
关于如何将上述内容组合到单个查询中,或以其他方式提高效率的任何想法?
答案 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