4

I would like to add a system of points, ranks and badges in my rails app.

The merit gem looks cool, but I want to make sure how it works before using it.

The way you define badges

# app/models/merit/badge_rules.rb
grant_on 'comments#vote', :badge => 'relevant-commenter', :to => :user do |comment|
  comment.votes.count == 5
end

and points

# app/models/merit/point_rules.rb
score 10, :to => :post_creator, :on => 'comments#create' do |comment|
  comment.title.present?
end

suggest that the action is done as a hook, just after the action (comments#vote or comments#create) in those cases. I havn't looked how the calculation/attribution of badges and points work yet so I am not sure.

As my app will evolve over time, I would like to be able to change the point and badges rules and re-evaluate them. Eg: Say I first decide to grant 10 points on account activation. I would like to be able to change it to 20 and then all activated profiles are re-evaluated and get a +10 point increase. Same thing for badges.

Does this gem support that ?

Charles
  • 50,943
  • 13
  • 104
  • 142
Benjamin Crouzier
  • 40,265
  • 44
  • 171
  • 236
  • 1
    Also, what if you wanted to add points dynamically - say, based on an attribute? (for instance, score resource.points_worth, :to => :user, :on 'task#answe') – nicohvi Apr 09 '13 at 17:52

1 Answers1

10

It is possible to recompute reputation in an app with merit gem. Merit keeps the history of which actions triggered which point/badge granting in Merit::Action model, which is mapped to merit_actions table.

Following script should work (do a back up first, as I didn't do this in production yet):

# 1. Reset all badges/points granting
Merit::BadgesSash.delete_all
Merit::Score::Point.delete_all

# 1.1 Optionally reset activity log (badges/points granted/removed until now)
Merit::ActivityLog.delete_all

# 2. Mark all `merit_actions` as unprocessed
Merit::Action.all.map{|a| a.update_attribute :processed, false }

# 3. Recompute reputation rules
Merit::Action.check_unprocessed
Merit::RankRules.new.check_rank_rules

Notes on merit internals ("General merit workflow" wiki page).

TuteC
  • 4,342
  • 30
  • 40
  • It does recalculate fine, but is there an option to reprocess rules and match each user? I mean I put merit in my app long down the road and I have trouble finding the right way to process rules for old users – DivinesLight Apr 04 '14 at 10:05
  • @BlackDivine do you have the "story" of the users of your app that would grant them reputation, at the time of plugging in merit? If so, we can recreate the `merit_actions` table to reflect what merit would have done, and call the `check_unprocessed` as if merit had existed all this time. – TuteC Apr 04 '14 at 13:57
  • If not, probably iterating "by hand" over the users in a background job may be easier. – TuteC Apr 04 '14 at 13:59
  • yes I have stories. My site is a photography site, and I grant badges on 1 photo upload, then 10, then 100 etc. So I want to allocate badges to users already with qualifying amount of photos. Now you suggest that the best method is to understand Actions model and then iterate users to craft unprocessed action records for each kind of badge rule I have written? – DivinesLight Apr 04 '14 at 18:05
  • I believe that would be too cumbersome, error-prone. I'd run a one off script: `User.find_each { |user| user.add_badge(x) if user.photos.count >= 1 }`, etc. – TuteC Apr 04 '14 at 21:16
  • so I write all the rules again? My whole question was that does "Merit" provides this or doesn't. which it doesn't. Which it should (IMHO) as its a huge use-case.X site now needs achievement system etc. And it's been live for some time. Also I would point out that if you have temporary badges, and for ex I have same badges, on 1 photo, 10 and 100. Whenever user uploads photo and say they are below 100, but increasing, merit adds to log "removing 100 photos badge" and triggers observer method which generates unnecessary calls as 100 photos badge wasn't earned in the first place... – DivinesLight Apr 05 '14 at 11:19
  • Merit's current DSL is certainly not the right tool for this problem. This an app specific concern. User could be meritable, but also others. Also, rules are now tied to controller actions and their state, they are not domain-level specifications. It's certainly interesting to me to explore another approach, something outside of Rails like logic programming: https://github.com/simplybusiness/Rools. – TuteC Apr 05 '14 at 17:14
  • I agree, it really is making more sense to write my own simple rules in models and then create a Badge model and then history of badges so they can be revoked. Thank you though :) – DivinesLight Apr 05 '14 at 17:38