0

I have a badge rule like this;

grant_on 'comments#create', badge: 'frequent-commenter', to: :user, temporary: true do |comment|
  comment.user.comments.where(:created_at.gte => (Date.today - 30)).count >= 20
end

User will lose the badge after sent a comment. But s/he will have the badge forever if s/he doesn't send a comment.

Is it possible to check temporary badges and remove the ones which are not valid anymore?

beydogan
  • 1,102
  • 1
  • 11
  • 23

1 Answers1

1

Can't run from the merit rules, as the comment local variable won't be there from a cron job. What I'd do is move the logic to the user model, and then call it both from the rule and from the cron job:

grant_on 'comments#create', badge: 'frequent-commenter', to: :user,
  temporary: true do |comment|

  comment.user.is_frequent_commenter?
end

class User
  def is_frequent_commenter?
    comments.where(:created_at.gte => (Date.today - 30)).count >= 20
  end
end

class RemoveInvalidBadgesJob
  def perform
    # Better done by direct database query?
    User.all.reject(&:is_frequent_commenter?).map do |user|
      user.rm_badge(1)
    end
  end
end
TuteC
  • 4,342
  • 30
  • 40
  • `User.all` can get really expensive, especially when there's a lot of users. I'd query directly for the users that are not frequent commenters using something like a join. – ben Nov 05 '14 at 01:08
  • Also, `find_each` works in batches of a 1,000 (and configurable). – TuteC Nov 05 '14 at 15:26
  • True. Why go over all the users in the DB though when we could select a subset directly? – ben Nov 05 '14 at 18:04
  • 1
    No reason at all, I did it this way to illustrate the idea, and because I don't know how each app is organized. Certainly doing SQL filtering is better, that's why the comment is there, in the form of a question. – TuteC Nov 05 '14 at 18:44