views:

300

answers:

2

I have a user model in which I have a method for seeing if the user has earned a "badge"

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

If they have earned a badge, the the award_badge method runs and gives the user the associated badge. Can I do something like this?

def check_if_badges_earned(user)
  if user.recipes.count > 10
  flash.now[:notice] = "you got a badge!"
  award_badge(1)
end

Bonus Question! (lame, I know)

Where would the best place for me to keep all of these "conditions" for which my users could earn badges, similar to stackoverflows badges I suppose. I mean in terms of architecture, I already have badge and badgings models.

How can I organize the conditions in which they are earned? some of them are vary complex, like the user has logged in 100 times without commenting once. etc. so there doesn’t seem to be a simple place to put this sort of logic since it spans pretty much every model.

+2  A: 

Have a look at Shapado project, it's an opensource Rails based project similar to Stackoverflow. Check out the code and get the answers.

Notice that Shapado uses MongoDB for storage, but the result is still the same for you.

khelll
+4  A: 

I'm sorry for you but the flash hash is not accessible in models, it gets created when the request is handled in your controller. You still can use implement your method storing the badge infos (flash message included) in a badge object that belongs to your users:

class Badge
  # columns:
  #    t.string :name

  # seed datas:
  #    Badge.create(:name => "Recipeador", :description => "Posted 10 recipes")
  #    Badge.create(:name => "Answering Machine", :description => "Answered 1k questions")
end

class User
  #...
  has_many :badges      

  def earn_badges
    awards = []
    awards << earn(Badge.find(:conditions => { :name => "Recipeador" })) if user.recipes.count > 10
    awards << earn(Badge.find(:conditions => { :name => "Answering Machine" })) if user.answers.valids.count > 1000 # an example
    # I would also change the finds with some id (constant) for speedup 
    awards
  end
end

then:

class YourController
  def your_action
    @user = User.find(# the way you like)...
    flash[:notice] = "You earned these badges: "+ @user.earn_badges.map(:&name).join(", ")
    #...
  end
end
makevoid
A damn good answer.
Joseph Silvashy