2009-11-15 15 views
1

奇怪的是,其中大部分都是按照已經寫好的方式工作的,但我不知道如何評估current_user是否有徽章(所有關係都是正確的,我我只能在我的課程中遇到麻煩(應該將其部分移到lib或其他內容中),而不管這個問題具體是1)檢查當前用戶是否有記錄,以及2)如果不創建相應的新記錄。在我的用戶類中獲得`current_user`

如果有更簡單或更好的方法來做到這一點,請分享。以下是我:

# Recipe Controller 
class RecipesController < ApplicationController 
    def create 
    # do something 
    if @recipe.save 
    current_user.check_if_badges_earned(current_user) 
    end 
end 

,從而爲這一點,它肯定看起來凌亂,我想爲它只是check_if_badges_earned,而不必通過current_user到方法,但可能需要因爲它可能並不總是當前用戶啓動此方法。

# User model 
class User < ActiveRecord::Base 

    def check_if_badges_earned(user) 
    if user.recipes.count > 10 
     award_badge(1, user) 
    end 
    if user.recipes.count > 20 
     award_badge(2, user) 
    end 
    end 

    def award_badge(badge_id, user) 
    #see if user already has this badge, if not, give it to them! 
    unless user.badgings.any? { |b| b[:badge_id] == badge_id} 
     @badging = Badging.new(:badge_id => badge_id, :user_id => user) 
     @badging.save 
    end 
    end 

end 

因此,儘管第一種方法(check_if_badges_earned)似乎excucte罰款,只有當條件滿足時,問題發生在award_badge()方法本身的表達unless user.badgings.any? { |b| b[:badge_id] == badge_id}始終計算爲真給運行award_badge(),所以用戶給予徽章,即使它已經有相同的一個(由badge_id),其次是問題是,它總是將user_id保存爲1.

關於如何去調試這個任何想法都會很棒!

回答

2

不管你是否需要上述current_user行爲,award_badge應該只是作用於一個普通實例方法self而不是根據傳遞的user參數採取行動(check_if_badges_earned也是如此)。在您的award_badge方法中,嘗試find_or_create_by_...而不是您當前擁有的邏輯。例如,試試這個:

class User < ActiveRecord::Base 
    # ... 

    def award_badge(badge_id) 
    badgings.find_or_create_by_badge_id(badge_id) 
    end 
end 

要訪問你的模型類的current_user,我有時喜歡使用線程局部變量。它確實模糊了MVC的分離,但有時這種耦合在應用程序中是必需的。

在你的ApplicationController,存儲current_user在線程局部變量:

class ApplicationController < ActionController::Base 
    before_filter :set_thread_locals 

    private 

    # Store thread-local variables so models can access them (Hackish, but useful) 
    def set_thread_locals 
    Thread.current[:current_user] = current_user 
    end 
end 

添加一個新的類方法的ActiveRecord的模型返回current_user(你也可以擴展的ActiveRecord :: Base的,使這個適用於所有型號):

class User < ActiveRecord::Base 
    def self.current_user 
    Thread.current[:current_user] 
    end 
end 

然後,你就可以用self.class.current_user訪問當前用戶在User模型的實例方法。

+0

這是一個很好的提示,我可以看到我可以在我的應用程序中的其他地方使用它,它實際上並不是超級黑客(或許,但是如果將它與我的工作區相比,它更接近我想要的MVC約定)謝謝瑞恩! – 2009-11-15 22:07:26

+0

和btw ...我是LMGTFY的粉絲,只是意識到你創造了它。真棒。 – 2009-11-15 22:38:56

+0

噢,哈克,謝謝,但要把道具給我的犯罪夥伴吉姆加文(http://www.thegarvin.com/)。 – 2009-11-15 23:04:55

1

你首先需要做的就是使這些方法的類方法(call on self),避免不必要地傳遞用戶引用。

然後,在你award_badge方法,你應該在標誌狀態添加到Badgings用戶的列表,如:user.badgings << Badging.new(:badge_id => badge_id)

+0

這個答案沒有意義。類方法不會避免用戶引用。此外,如果用戶尚未擁有該徽章,則其原始代碼只會添加徽章。你的'award_badge'片段會產生重複的徽章,這不是他以前的樣子。 – 2009-11-15 22:24:15

+0

@Ryan:你說的是類方法的一部分。不知道我爲什麼這麼想。實際上我的意思是說,因爲他有一個對當前用戶的引用,他不需要傳遞該引用,他可以直接調用實例方法。對於第二部分,我只是展示瞭如何將它與用戶相關聯,這確實是一個片段。我沒有指定放棄他的if語句。 – JRL 2009-11-15 23:08:41

相關問題