2013-10-07 17 views
2

我有一個用戶和帖子模型,並使用acts_as_votable gem(它給了我一張「票」表)來upvote/downvote一個帖子。我想爲每個用戶分配業力,其中karma是用戶從他/她的帖子中獲得的upvotes數量減去downvotes的總數量。在用戶的帖子上計算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

不僅關於效率,這樣的設計在OOP方面並不好。用戶模型超出其範圍考慮太多。噶是屬於用戶的東西,不應該與其他任何東西捆綁在一起。

更好的方法是將「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 
+0

你是什麼意思,「......這樣的設計在面向對象方面不太好,用戶模型考慮的太多了」。這是不好的設計,因爲我試圖訪問不屬於User模型而是Post模型的投票,還是因爲我正在訪問由關係定義的帖子,而不是用戶表上的實際屬性?是user.posts沒關係,但user.posts.first.votes不好?或者他們都不好? 另外,目前我有一個單獨的votes_controller。像上面演示的那樣,在posts_controller中進行投票操作會更安心嗎? – steve

+0

Steve,對於你的第一個說法,是的,'user.posts'沒問題,但'user.posts.first.votes'不好。這個用戶的手太長了:)他碰到了不屬於他的東西。對於投票,我認爲把它們放在PostsController中更自然。即使你有更多的投票評論,你也可以在評論控制器中投票。 –